我正在使用以下帖子的代码:
首先,我将使用控制器操作的正确值填充数组变量.
使用下面的代码我认为只需在JavaScript代码中添加以下行就可以非常简单:
data["__RequestVerificationToken"] = $('[name=__RequestVerificationToken]').val();
该<%= Html.AntiForgeryToken() %>
是在其正确的位置,动作有[ValidateAntiForgeryToken]
但我的控制器动作一直说:"无效的伪造令牌"
我在这做错了什么?
data["fiscalyear"] = fiscalyear; data["subgeography"] = $(list).parent().find('input[name=subGeography]').val(); data["territories"] = new Array(); $(items).each(function() { data["territories"].push($(this).find('input[name=territory]').val()); }); if (url != null) { $.ajax( { dataType: 'JSON', contentType: 'application/json; charset=utf-8', url: url, type: 'POST', context: document.body, data: JSON.stringify(data), success: function() { refresh(); } }); }
小智.. 60
自MVC 4以来,您不需要ValidationHttpRequestWrapper解决方案.根据此链接.
将标记放在标题中.
创建一个过滤器.
将属性放在您的方法上.
这是我的解决方案:
var token = $('input[name="__RequestVerificationToken"]').val(); var headers = {}; headers['__RequestVerificationToken'] = token; $.ajax({ type: 'POST', url: '/MyTestMethod', contentType: 'application/json; charset=utf-8', headers: headers, data: JSON.stringify({ Test: 'test' }), dataType: "json", success: function () {}, error: function (xhr) {} }); [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)] public class ValidateJsonAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter { public void OnAuthorization(AuthorizationContext filterContext) { if (filterContext == null) { throw new ArgumentNullException("filterContext"); } var httpContext = filterContext.HttpContext; var cookie = httpContext.Request.Cookies[AntiForgeryConfig.CookieName]; AntiForgery.Validate(cookie != null ? cookie.Value : null, httpContext.Request.Headers["__RequestVerificationToken"]); } } [HttpPost] [AllowAnonymous] [ValidateJsonAntiForgeryToken] public async TaskMyTestMethod(string Test) { return Json(true); }
优雅的解决方案,非常好的使用属性和结果更清晰的代码. (2认同)
Darin Dimitr.. 49
有意义的是,应该处理此请求的控制器操作以及标记为[ValidateAntiForgeryToken]
期望的参数被调用__RequestVerificationToken
与请求一起被POST.
没有这样的参数POST,因为你使用JSON.stringify(data)
它将表单转换为其JSON表示,因此抛出异常.
所以我可以在这看到两种可能的解决方案
数字1:使用x-www-form-urlencoded
而不是JSON
发送您的请求参数:
data["__RequestVerificationToken"] = $('[name=__RequestVerificationToken]').val(); data["fiscalyear"] = fiscalyear; // ... other data if necessary $.ajax({ url: url, type: 'POST', context: document.body, data: data, success: function() { refresh(); } });
数字2:将请求分成两个参数:
data["fiscalyear"] = fiscalyear; // ... other data if necessary var token = $('[name=__RequestVerificationToken]').val(); $.ajax({ url: url, type: 'POST', context: document.body, data: { __RequestVerificationToken: token, jsonRequest: JSON.stringify(data) }, success: function() { refresh(); } });
因此,在所有情况下,您都需要POST __RequestVerificationToken
值.
自MVC 4以来,您不需要ValidationHttpRequestWrapper解决方案.根据此链接.
将标记放在标题中.
创建一个过滤器.
将属性放在您的方法上.
这是我的解决方案:
var token = $('input[name="__RequestVerificationToken"]').val(); var headers = {}; headers['__RequestVerificationToken'] = token; $.ajax({ type: 'POST', url: '/MyTestMethod', contentType: 'application/json; charset=utf-8', headers: headers, data: JSON.stringify({ Test: 'test' }), dataType: "json", success: function () {}, error: function (xhr) {} }); [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)] public class ValidateJsonAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter { public void OnAuthorization(AuthorizationContext filterContext) { if (filterContext == null) { throw new ArgumentNullException("filterContext"); } var httpContext = filterContext.HttpContext; var cookie = httpContext.Request.Cookies[AntiForgeryConfig.CookieName]; AntiForgery.Validate(cookie != null ? cookie.Value : null, httpContext.Request.Headers["__RequestVerificationToken"]); } } [HttpPost] [AllowAnonymous] [ValidateJsonAntiForgeryToken] public async TaskMyTestMethod(string Test) { return Json(true); }
有意义的是,应该处理此请求的控制器操作以及标记为[ValidateAntiForgeryToken]
期望的参数被调用__RequestVerificationToken
与请求一起被POST.
没有这样的参数POST,因为你使用JSON.stringify(data)
它将表单转换为其JSON表示,因此抛出异常.
所以我可以在这看到两种可能的解决方案
数字1:使用x-www-form-urlencoded
而不是JSON
发送您的请求参数:
data["__RequestVerificationToken"] = $('[name=__RequestVerificationToken]').val(); data["fiscalyear"] = fiscalyear; // ... other data if necessary $.ajax({ url: url, type: 'POST', context: document.body, data: data, success: function() { refresh(); } });
数字2:将请求分成两个参数:
data["fiscalyear"] = fiscalyear; // ... other data if necessary var token = $('[name=__RequestVerificationToken]').val(); $.ajax({ url: url, type: 'POST', context: document.body, data: { __RequestVerificationToken: token, jsonRequest: JSON.stringify(data) }, success: function() { refresh(); } });
因此,在所有情况下,您都需要POST __RequestVerificationToken
值.
我刚刚在我当前的项目中实现了这个实际问题.我为所有需要经过身份验证的用户的Ajax POST做了这件事.
首先,我决定挂钩我的jQuery Ajax调用,所以我不要经常重复自己.此JavaScript代码段确保所有ajax(post)调用都将我的请求验证令牌添加到请求中.注意:.NET框架使用名称__RequestVerificationToken,因此我可以使用标准的Anti-CSRF功能,如下所示.
$(document).ready(function () { securityToken = $('[name=__RequestVerificationToken]').val(); $('body').bind('ajaxSend', function (elm, xhr, s) { if (s.type == 'POST' && typeof securityToken != 'undefined') { if (s.data.length > 0) { s.data += "&__RequestVerificationToken=" + encodeURIComponent(securityToken); } else { s.data = "__RequestVerificationToken=" + encodeURIComponent(securityToken); } } }); });
在您需要令牌可用于上述JavaScript代码的视图中,只需使用常见的HTML-Helper即可.您基本上可以在任何地方添加此代码.我将它放在if(Request.IsAuthenticated)语句中:
@Html.AntiForgeryToken() // You can provide a string as salt when needed which needs to match the one on the controller
在您的控制器中,只需使用标准的ASP.NET MVC反CSRF机制.我是这样做的(尽管我实际上使用了盐).
[HttpPost] [Authorize] [ValidateAntiForgeryToken] public JsonResult SomeMethod(string param) { // Do something return Json(true); }
使用Firebug或类似工具,您可以轻松查看POST请求现在如何附加__RequestVerificationToken参数.
您可以设置$ .ajax 的traditional
属性并将其设置为true
,以便以url编码的形式发送json数据.一定要设置type:'POST'
.使用此方法,您甚至可以发送数组,而不必使用JSON.stringyfy或服务器端的任何更改(例如,创建自定义属性来嗅探头)
我在ASP.NET MVC3和jquery 1.7设置上试过这个,它正在运行
以下是代码段.
var data = { items: [1, 2, 3], someflag: true}; data.__RequestVerificationToken = $(':input[name="__RequestVerificationToken"]').val(); $.ajax({ url: 'Test/FakeAction' type: 'POST', data: data dataType: 'json', traditional: true, success: function (data, status, jqxhr) { // some code after succes }, error: function () { // alert the error } });
这将与具有以下签名的MVC操作匹配
[HttpPost] [Authorize] [ValidateAntiForgeryToken] public ActionResult FakeAction(int[] items, bool someflag) { }
我持有令牌在我的JSON对象,我结束了修改ValidateAntiForgeryToken类检查的InputStream中的请求对象时的职位是JSON.我写了一篇关于它的博客文章,希望你会发现它很有用.
您无法验证contentType类型的内容:'application/json; 字符集= UTF-8' ,因为你的日期将在没有上传表单请求的性质,但是在InputStream的财产,你将永远不会有这样的Request.Form ['__ RequestVerificationToken’.
这将始终为空,验证将失败.
当您收到发布的JSON时,您将不必验证AntiForgeryToken.
原因是AntiForgeryToken已被创建以防止CSRF.由于您无法将AJAX数据发布到其他主机,并且HTML表单无法提交JSON作为请求正文,因此您无需保护您的应用程序免受已发布的JSON的影响.