0

我有ASP.NET MVC 5应用程序使用。净4.5.1。该应用程序有几个jQuery ajax post方法将POST数据发送到服务器。为了防止跨站请求伪造(XSRF)我已经加入_layout.cshtmlValidateAntiForgeryToken不工作与ajax后asp.net mvc后

@Html.AntiForgeryToken() 

并且还JavaScript的,其与所有的Ajax POST发送令牌的HTTPHeader

$(document).ajaxSend(function (event, jqXHR, ajaxOptions) { 
      if (ajaxOptions.type === 'POST') { 
       jqXHR.setRequestHeader('__RequestVerificationToken', $('input[name="__RequestVerificationToken"]').val()); 
      }     
     }); 

,然后在控制器的以下操作方法我有

[ValidateAntiForgeryToken]   
    [HttpPost] 
    public ActionResult Save(MyModel model) 
    { 
     //save and return json data 
    } 

然而ValidateAntiForgeryToken thorwing例外

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

我确认__RequestVerificationToken正在为每个Ajax POST添加到httpheader。

我有一个使用ASP.NET开发的核心另一个应用程序和我有相同的功能有(除头名是RequestVerificationToken而不是__RequestVerificationToken)及其在了ASP.NET的核心工作。

为什么在标题包含在标题中时,ASP.NET MVC中不起作用? ASP.NET Core vs ASP.NET MVC 5中有没有区别ValidateAntiForgeryToken?

+0

可能的复制和Html.AntiForgeryToken( )](http://stackoverflow.com/questions/4074199/jquery-ajax-calls-and-the-html-antiforgerytoken) – VahidN

+0

@VahidN它不是同一个问题。我以前通过提供的链接。 – LP13

回答

1

要解决您的问题,除setRequestHeader之外,所有内容都保持不变。通过__RequestVerificationToken在请求主体

data: { 
       __RequestVerificationToken: $('input[name="__RequestVerificationToken"]').val(), 
       // Other properties of data 
      }, 
+0

是在asp.net mvc中,如果我添加到数据然后它的工作?不过,我想在asp.net核心它可以工作,无论你添加'数据'或在'头'。为了解决我的问题,我实现了自定义ValidateAntiForgeryTokenAttribute。 – LP13

+0

Asp.net核心检查令牌的标题和正文。 – Kaushal

0

为了解决我的问题,我已经实现了定制ValidateAntiForgeryToken。我已决定将标记包含在标题中。

  1. 我有整个申请的几个AJAX POST方法,所以不是 将它放在每个操作方法,我想在全球范围内对其进行验证。
  2. 在客户端,我想隐式地为每个ajax POST请求包含令牌。 (应用程序也有剑道网格,这使得AJAX POST请求得到的数据)
  3. 阿贾克斯后data可能是JSON对象或序列化形式,这 使得添加__RequestVerificationTokendata点点 棘手的(并非不可能),特别是当我想要在全球范围内处理它 。

因此,这里是我的完整代码

过滤

public class ValidatePostAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter 
    { 
     private const string _tokenKey = "__RequestVerificationToken"; 
     public void OnAuthorization(AuthorizationContext filterContext) 
     { 
      if (filterContext == null) 
      { 
       throw new ArgumentNullException("filterContext"); 
      } 

      if (filterContext.HttpContext.Request.HttpMethod.ToUpper() == "POST") 
      { 
       if (filterContext.HttpContext.Request.IsAjaxRequest()) 
       { 
        if (filterContext.HttpContext.Request.Cookies.Get(_tokenKey) == null || 
        filterContext.HttpContext.Request.Headers.Get(_tokenKey) == null) 
        { 
         throw new HttpPostAntiForgeryException("Invalid Verification Token."); 
        } 

        AntiForgery.Validate(filterContext.HttpContext.Request.Cookies[_tokenKey].Value, filterContext.HttpContext.Request.Headers[_tokenKey]); 
       }     
      } 
     } 
    } 

异常

public sealed class HttpPostAntiForgeryException : HttpException 
{ 
    public HttpPostAntiForgeryException() 
    { 
    } 
    public HttpPostAntiForgeryException(string message) : base(message) 
    { 
    } 
} 

添加过滤器全球

public class FilterConfig 
{ 
    public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    { 
     filters.Add(new HandleErrorAttribute()); 
     filters.Add(new AuthorizeAttribute() { Order = 0 }); 
     filters.Add(new ValidatePostAntiForgeryTokenAttribute() { Order = 1 }); 
    } 
} 

_layout.cshtml - JS添加令牌

$.ajaxPrefilter(function (options, originalOptions, jqXHR) { 
       if (originalOptions.type === "POST") 
        jqXHR.setRequestHeader('__RequestVerificationToken', $('input[name="__RequestVerificationToken"]').val()); 
      }); 

添加令牌[jQuery的Ajax调用的_layout.cshtml

@Html.AntiForgeryToken()