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

我不知道如何在 ajax 中使用 AntiForgeryToken。

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

这是我的代码 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”不存在。

谢谢。

【问题讨论】:

    标签: jquery ajax model-view-controller antiforgerytoken


    【解决方案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);
      }
      

      很简单,试试吧……

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-04-08
        • 2011-02-23
        • 1970-01-01
        • 2011-12-09
        • 2013-01-06
        • 2015-06-25
        相关资源
        最近更新 更多