当前位置:  开发笔记 > 编程语言 > 正文

如何使用$ .ajax发布JSON数据时提供AntiForgeryToken?

如何解决《如何使用$.ajax发布JSON数据时提供AntiForgeryToken?》经验,为你挑选了7个好方法。

我正在使用以下帖子的代码:

首先,我将使用控制器操作的正确值填充数组变量.

使用下面的代码我认为只需在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 Task MyTestMethod(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值.



1> 小智..:

自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 Task MyTestMethod(string Test)
{
    return Json(true);
}


优雅的解决方案,非常好的使用属性和结果更清晰的代码.

2> Darin Dimitr..:

有意义的是,应该处理此请求的控制器操作以及标记为[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 2期货/ MVC 3类JsonValueProviderFactory对字符串化的json对象进行水合,你就可以自己手动处理水合作用,这样你就可以忽略__RequestVerificationToken.如果我没有告诉contentType期望$ .ajax的json,那么处理验证令牌,但json对象没有水合.如果我告诉set json contentType那么Anti-Forgery验证失败.因此,我将关注TWith2Sugars解决方案.但上面确实有效!
场景#2是否适用于MVC 3.我尝试过但没有成功.

3> 360Airwalk..:

我刚刚在我当前的项目中实现了这个实际问题.我为所有需要经过身份验证的用户的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参数.


在我看来你错过了这一点.您的代码只能使用请求数据有效负载作为`application/x-www-form-urlencoded`内容类型.OP希望将他的请求数据有效负载发送为`application/json`.将`&__ Request ...`附加到JSON有效负载应该会失败.(他没有要求JSON响应,这是您的代码示例,但是对于JSON请求.)

4> N30..:

您可以设置$ .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)
{
}



5> TWith2Sugars..:

我持有令牌在我的JSON对象,我结束了修改ValidateAntiForgeryToken类检查的InputStream中的请求对象时的职位是JSON.我写了一篇关于它的博客文章,希望你会发现它很有用.



6> 小智..:

您无法验证contentType类型的内容:'application/json; 字符集= UTF-8' ,因为你的日期将在没有上传表单请求的性质,但是在InputStream的财产,你将永远不会有这样的Request.Form ['__ RequestVerificationToken’.

这将始终为空,验证将失败.



7> Antoine Lecl..:

当您收到发布的JSON时,您将不必验证AntiForgeryToken.

原因是AntiForgeryToken已被创建以防止CSRF.由于您无法将AJAX数据发布到其他主机,并且HTML表单无法提交JSON作为请求正文,因此您无需保护您的应用程序免受已发布的JSON的影响.


这并不总是正确的.可以使用HTML表单伪造JSON帖子.如果查看AjaxRequestExtensions.IsAjaxRequest,它会在请求正文中检查"X-Requested-With",而不仅仅是标题.因此,要么您自己进行验证以确保使用AJAX发布数据,要么添加AntiForgeryToken.
谁说你不能把数据传给另一个主机?http://stackoverflow.com/questions/298745/how-do-i-send-a-cross-domain-post-request-via-javascript
如果您可以要求Action仅对AJAX请求可用,则会出现这种情况,但您不能.就像声明的那样.您唯一能做的就是将Action锁定为仅接受application/json作为请求的主体.但是我并不熟悉你如何将MVC中的Action限制为特定的内容类型,你必须做很多我猜的定制工作.据我所知,这不是一个开箱即用的功能.
推荐阅读
mobiledu2402851373
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有