我有一张表格,用户可以在没有登录的情况下发布.但是,如果他的电子邮件被识别,则需要密码.密码表格通过Ajax进行验证,如果成功提交主表单.两种形式都需要有效的AntiForgeryToken.
捕获是,作为双产品的密码检查也会对用户进行签名(来自客户端的要求).这使令牌无效,主表单无法发送.
我已经以编程方式生成了一个新的令牌,但是我无法让它工作.
关于如何解决这个问题的任何想法?
最终解决方案
我发现this的问题有助于打造反思.然而,这正是在正常情况下,您将避免黑客内部类型的主要原因,这些类型是在版本之间的程序集之间进行的.贝蒂建议,使用ILSpy来查找东西.
这是最终的代码.
if (signIn) FormsAuth.SignIn(user.Email,false); var mvcAssembly = typeof(AntiForgery).Assembly; var afdType = mvcAssembly.GetType("System.Web.Helpers.AntiForgeryData"); string fieldName = Convert.ToString(afdType.InvokeMember( "GetAntiForgeryTokenName",BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod,null,new object[] { null })); var serializerType = mvcAssembly.GetType("System.Web.Helpers.AntiForgeryDataSerializer"); var serializerCtor = serializerType.GetConstructor(new Type[0]); object serializer = serializerCtor.Invoke(new object[0]); string text = HttpContext.Request.Form[fieldName]; object antiForgeryData = serializerType.InvokeMember("Deserialize",BindingFlags.InvokeMethod,serializer,new object[] { text }); afdType.GetProperty("Username").SetValue(antiForgeryData,signIn ? user.Email : string.Empty,null); string newToken = Convert.ToString(serializerType.InvokeMember( "Serialize",new object[] { antiForgeryData })); return Content(JsonConvert.SerializeObject(new { success = true,newAntiForgeryToken = newToken }),Constant.JsonContentType);
升级为WebPages 2.0
var mvcAssembly = typeof(AntiForgery).Assembly; var afdType = mvcAssembly.GetType("System.Web.Helpers.AntiXsrf.AntiForgeryToken"); //string fieldName = Convert.ToString(afdType.InvokeMember( // "GetAntiForgeryTokenName",// BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod,// null,// new object[] { null })); string fieldName = "__RequestVerificationToken"; var serializerType = mvcAssembly.GetType("System.Web.Helpers.AntiXsrf.AntiForgeryTokenSerializer"); var serializerCtor = serializerType.GetConstructor(new Type[0]); object serializer = serializerCtor.Invoke(new object[0]); string text = HttpContext.Request.Form[fieldName]; string newToken = String.Empty; if (!String.IsNullOrEmpty(text)) { object antiForgeryToken = serializerType.InvokeMember("Deserialize",new object[] { text }); afdType.GetProperty("Username").SetValue(antiForgeryToken,null); newToken = Convert.ToString(serializerType.InvokeMember( "Serialize",new[] { antiForgeryToken })); }@H_403_20@
解决方法
当前用户以表单数据存储在防伪令牌中,并与回覆时的当前用户进行比较.
您应该能够以与Phil Haack在this post中相同的方式在回发时拉出表单令牌.
然后使用AntiForgeryDataSerializer类对令牌进行反序列化,更新当前用户,将其重新序列化,并在检查之前将其放回表单中.或者使用您自己的属性来完全替换验证方法.
或者,而不是在主窗体回发上更新它,您可以尝试使用密码ajax请求发送更新的令牌并更新表单.无论哪种方式,基本方法是一样的,反序列化,更新用户,序列化,替换令牌.
string antiForgeryTokenName = AntiForgeryData.GetAntiForgeryTokenName(null); string text = context.Request.Form[antiForgeryTokenName]; AntiForgeryDataSerializer serializer = new AntiForgeryDataSerializer(); AntiForgeryData antiForgeryData = serializer.Deserialize(text); antiForgeryData.Username = AntiForgeryData.GetUsername(context.User); string newToken = serializer.Serialize(antiForgeryData);
AntiForgeryDataSerializer和AntiForgeryData是内部类,所以你必须使用一些基本的反射来调用它们的方法.
@H_403_20@ @H_403_20@ 原文链接:https://www.f2er.com/aspnet/250110.html