是否可以在XMLHttpRequest标头中包含antiforgerytoken?

时间:2017-12-27 02:45:16

标签: jquery asp.net-mvc-5 xmlhttprequest http-post

我正在使用名为Slim的库,将图像上传到我的asp.net MVC项目。

JQuery库使用XMLHttpRequest向服务器发送请求,我已经完成了所有手册,并且没有关于如何将防伪标记包含到服务器中。

所以我在发送之前手动添加了这一行:

data.__RequestVerificationToken = $('input[name="__RequestVerificationToken"]').val();

即使令牌包含在数据中,Asp.net MVC过滤器: ValidateJsonAntiForgeryTokenAttribute 也无法识别它,因为它期望令牌位于标头。这是服务器上的验证码:

AntiForgery.Validate(cookie != null ? cookie.Value : null,
                             httpContext.Request.Headers["__RequestVerificationToken"]);

这里是库的send函数,我在buttom添加了额外的行以包含令牌。如何在标题中包含令牌?

var send = function send(url, data, requestDecorator, progress, success, err) {

var xhr = new XMLHttpRequest();

// if progress callback defined handle progress events
if (progress) {
    xhr.upload.addEventListener('progress', function (e) {
        progress(e.loaded, e.total);
    });
}

// open the request
xhr.open('POST', url, true);

// if request decorator defined pass XMLHttpRequest instance to decorator
if (requestDecorator) {
    requestDecorator(xhr);
}

// handle state changes
xhr.onreadystatechange = function () {

    if (xhr.readyState === 4 && xhr.status >= 200 && xhr.status < 300) {

        var text = xhr.responseText;

        // if no data returned from server assume success
        if (!text.length) {
            success();
            return;
        }

        // catch possible PHP content length problem
        if (text.indexOf('Content-Length') !== -1) {
            err('file-too-big');
            return;
        }

        // if data returned it should be in suggested JSON format
        var obj = void 0;
        try {
            obj = JSON.parse(xhr.responseText);
        } catch (e) {}

        // if is failure response
        if ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' && obj.status === 'failure') {
            err(obj.message);
            return;
        }

        success(obj || text);
    } else if (xhr.readyState === 4) {

        var _obj = void 0;
        try {
            _obj = JSON.parse(xhr.responseText);
        } catch (e) {}

        // if is clean failure response
        if ((typeof _obj === 'undefined' ? 'undefined' : _typeof(_obj)) === 'object' && _obj.status === 'failure') {
            err(_obj.message);
            return;
        }

        err('fail');
    }
};

// I have added this line to library to include anti forgery token
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
data.__RequestVerificationToken = $('input[name="__RequestVerificationToken"]').val();

// do request
xhr.send(data);

}; `

2 个答案:

答案 0 :(得分:1)

您需要在标题中设置antiforgerytoken,如下所示:

xhr.setRequestHeader('__RequestVerificationToken', $('input[name="__RequestVerificationToken"]').val());

有关XMLHttpRequest的更多信息,请参阅XMLHttpRequest.setRequestHeader

要验证控制器中标题中传递的AntiforgeryToken,您需要创建自己的过滤器,如下所示:

[HttpPost]
[ValidateJsonAntiForgeryToken]
public ActionResult MySlimAction()
{
    /* your Save controller logic goes here */
}

将此过滤器定义作为新类添加到Filters文件夹中:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public sealed 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"]);
    }
}

对于您的特定库Slim Image Cropper,您可以在初始化Slim时使用 willRequest 回调:

var cropper = $('#my-cropper-selector').slim({
  willRequest: function (xhr) {
    xhr.setRequestHeader('__RequestVerificationToken', $('input[name="__RequestVerificationToken"]').val());
  },
  ratio: 'free',
  push: true,
  service: '/MyController/MySlimAction'
  /* other options go here */
});

答案 1 :(得分:0)

如果有人仍在为此苦苦挣扎,这是一个解决方案:

var request = new XMLHttpRequest(); request.setRequestHeader('RequestVerificationToken',$('input [name =“ __ RequestVerificationToken”]')。val());

不带'__',因此无法正常工作:

var request = new XMLHttpRequest(); request.setRequestHeader('__ RequestVerificationToken',$('input [name =“ __ RequestVerificationToken”]')。val());

在Backend中,您可以使用[ValidateAntiForgeryToken]内置的已知属性:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteTenantRole()

工作正常。 无需创建自己的过滤器属性