如何在ajax中使用AntiForgeryToken

时间:2015-05-11 05:35:43

标签: jquery ajax model-view-controller antiforgerytoken

我不知道如何在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。错误总是一样的:

所需的防伪表格字段&#34; __ RequestVerificationToken&#34;不存在。

感谢。

2 个答案:

答案 0 :(得分:1)

这对我有用。

提供正确的命名空间和引用,并将下面的代码保存为类似ValidateJsonAntiForgeryTokenAttribute.cs的内容。在接受AJAX POST请求的控制器操作中,只需使用该属性进行装饰:

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

在您的客户端脚本中,只需在某处包含@Html.AntiForgeryToken()。当执行AJAX调用时,将该隐藏字段中的值传递给AJAX请求标头...下面的示例使用了角度,因此请根据您正在使用的客户端进行调整...

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;
                }
            }
        }
    }

答案 1 :(得分:0)

简单地,您可以对服务器进行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);
}

很简单,尝试一下...