如何在 ajax 中使用 AntiForgeryToken

Posted

技术标签:

【中文标题】如何在 ajax 中使用 AntiForgeryToken【英文标题】:how to use AntiForgeryToken in ajax 【发布时间】:2015-07-21 12:30:46 【问题描述】:

我不知道。

我在 SO 上找到了以下答案,但它们对我不起作用:

jQuery Ajax calls and the html.AntiForgeryToken() include antiforgerytoken in ajax post ASP.NET MVC How to make ajax request with anti-forgery token in mvc

这是我的代码 html:

@using (Html.BeginForm())
                    
                        @Html.AntiForgeryToken()
                        @Html.TextBoxFor(model => model.UserName, new  @class = "form-control", id = "UserName", placeholder = @CMS.Resources.Resource.UserName )
                        @Html.PasswordFor(model => model.Password, new  @class = "form-control", id = "Password", placeholder = @CMS.Resources.Resource.Password )

                        <button id="LoginButton" class="k-button" type="submit">@CMS.Resources.Resource.Signin</button>
                    

javascript

$('#LoginButton').click(function (e) 
        if ($('form').valid()) 

            var data =  UserName: $('#UserName').val(), Password: $('#Password').val() ;
            var token = $('[name=__RequestVerificationToken]').val();
            var headers = ;
            headers["__RequestVerificationToken"] = token;

            $.ajax(
                type: 'POST',
                traditional: true,
                data: JSON.stringify(data),
                cache: false,
                headers: headers,
                dataType: 'json',
                url: '@Url.Action("LoginPanel", "Account")',
                contentType: "application/json; charset=utf-8",
                success: function (status) 
                ,
                error: function (status) 
                    alert(status);
                
            );
        
        e.preventDefault();
    );

控制器:

        [HttpPost, ValidateAntiForgeryToken]
    public JsonResult LoginPanel(LoginModel model)
    
        LoginStatus status = new LoginStatus();
        if (HttpContext.Request.IsAjaxRequest())
        
            if (ModelState.IsValid)
            
                ....
            
        
        return Json(status, JsonRequestBehavior.AllowGet);
    

以及其他尝试过的 JavaScript 代码模式。通过将值 __RequestVerificationToken 放在标头或数据中。错误总是一样的:

所需的防伪表单字段“__RequestVerificationToken”不存在。

谢谢。

【问题讨论】:

【参考方案1】:

这对我有用。

提供正确的命名空间和引用,并将下面的代码保存到 ValidateJsonAntiForgeryTokenAttribute.cs 之类的东西中,在接受 AJAX POST 请求的控制器操作中,只需使用该属性来装饰它,如下所示:

[HttpPost]
[ValidateJsonAntiForgeryToken]
public Task<ActionResult> HandleAjaxCall(string blah) 

在您的客户端脚本中,只需在某处包含@Html.AntiForgeryToken()。并且在进行 AJAX 调用时,将该隐藏字段中的值传递到 AJAX 请求标头中...下面的示例使用 angular,因此请根据您使用的任何客户端内容进行调整...

var details = angular.toJson(...);
var antiForgeryToken = $('input[name="__RequestVerificationToken"]').val();
     return $http(
            method: 'POST',
            headers:  '__RequestVerificationToken': antiForgeryToken ,
            url: '/ControllerName/HandleAjaxCall',
            data: details
     );

ValidateJsonAntiForgeryTokenAttribute.cs文件内容:

    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
    public class ValidateJsonAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
    
       public void OnAuthorization(AuthorizationContext filterContext)
        
            var request = filterContext.HttpContext.Request;
            if (filterContext == null)
            
                throw new ArgumentNullException("filterContext");
            

            var httpContext = new JsonAntiForgeryHttpContextWrapper(HttpContext.Current);

            try
            
                var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];
                var cookieValue = antiForgeryCookie != null
                       ? antiForgeryCookie.Value
                       : null;
                AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);
            
            catch (HttpAntiForgeryException ex)
            
                //Append where the request url.
                var msg = string.Format("0 from 1", ex.Message, httpContext.Request.Url);
                throw new HttpAntiForgeryException(msg);
            
        

        private class JsonAntiForgeryHttpContextWrapper : HttpContextWrapper
        
            readonly HttpRequestBase _request;
            public JsonAntiForgeryHttpContextWrapper(HttpContext httpContext)
                : base(httpContext)
            
                _request = new JsonAntiForgeryHttpRequestWrapper(httpContext.Request);
            

            public override HttpRequestBase Request
            
                get
                
                    return _request;
                
            
        

        private class JsonAntiForgeryHttpRequestWrapper : HttpRequestWrapper
        
            readonly NameValueCollection _form;

            public JsonAntiForgeryHttpRequestWrapper(HttpRequest request)
                : base(request)
            
                _form = new NameValueCollection(request.Form);
                if (request.Headers["__RequestVerificationToken"] != null)
                
                    _form["__RequestVerificationToken"] = request.Headers["__RequestVerificationToken"];
                
            

            public override NameValueCollection Form
            
                get
                
                    return _form;
                
            
        
    

【讨论】:

【参考方案2】:

简单地说,您可以向服务器发出 Ajax 调用(发帖),

Ajax 调用示例:

<script>
function SendData() 
    var token = $("[name='__RequestVerificationToken']").val();
    var options = 
        url: '@Url.Action("Create","Car")',
        type: "post",
        data: 
            __RequestVerificationToken: token,
            regNumber: $("#regNumber").val(),
            make: $("#make").val(),
            model: $("#model").val()
        
    ;
    $.ajax(options);

很简单,试试吧……

【讨论】:

以上是关于如何在 ajax 中使用 AntiForgeryToken的主要内容,如果未能解决你的问题,请参考以下文章

如何在使用 Reflux 的商店中使用 AJAX 获取初始状态

如何在 laravel 4 中使用 ajax

如何在ajax中使用django url?

如何在 Django 中使用 jQuery/Ajax 发布?

如何使用ajax在刀片中显示验证错误?

如何在codeigniter中使用ajax上传图片?