asp.net - 使用WebApi时,防伪Cookie token 和表单字段 token 不匹配

标签 asp.net asp.net-mvc asp.net-web-api csrf antiforgerytoken

我有一个单页应用程序(用户加载了一堆HTML/JS,然后发出AJAX请求,而无需再次调用MVC-仅通过WebAPI)。在WebAPI中,我具有以下内容:

public sealed class WebApiValidateAntiForgeryTokenAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(
        System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        if (actionContext == null)
        {
            throw new ArgumentNullException(nameof(actionContext));
        }
        if (actionContext.Request.Method.Method == "POST")
        {
            string requestUri = actionContext.Request.RequestUri.AbsoluteUri.ToLower();
            if (uriExclusions.All(s => !requestUri.Contains(s, StringComparison.OrdinalIgnoreCase))) // place some exclusions here if needed
            {
                HttpRequestHeaders headers = actionContext.Request.Headers;

                CookieState tokenCookie = headers
                    .GetCookies()
                    .Select(c => c[AntiForgeryConfig.CookieName]) // __RequestVerificationToken
                    .FirstOrDefault();

                string tokenHeader = string.Empty;
                if (headers.Contains("X-XSRF-Token"))
                {
                    tokenHeader = headers.GetValues("X-XSRF-Token").FirstOrDefault();
                }

                AntiForgery.Validate(!string.IsNullOrEmpty(tokenCookie?.Value) ? tokenCookie.Value : null, tokenHeader);
            }

        }
        base.OnActionExecuting(actionContext); // this is where it throws
    }
}

在Global.asax中注册:
    private static void RegisterWebApiFilters(HttpFilterCollection filters)
    {
        filters.Add(new WebApiValidateAntiForgeryTokenAttribute());
        filters.Add(new AddCustomHeaderFilter());
    }

有时,我在日志中看到The anti-forgery cookie token and form field token do not match错误。发生这种情况时,tokenCookie.valuetokenHeader都不为空。

在客户端,我所有的AJAX请求都使用以下内容:
beforeSend: function (request) {
     request.setRequestHeader("X-XSRF-Token", $('input[name="__RequestVerificationToken"]').attr("value"););
},

使用Razor在我的SPA页面上一次生成 token :
@Html.AntiForgeryToken()

我在Web.config中设置了机器 key 。

是什么原因造成的?

更新
我刚刚查看了日志,有时也看到以下内容:

The provided anti-forgery token was meant for user "", but the current user is "someuser@domain.com". a few seconds ago



当用户在登录时刷新其SPA实例时,会发生这种情况。然后SPA由于某种原因(User.Identity.IsAuthenticated为true)将其拖放到登录页面而不是内页中-由于该错误,他们无法登录。刷新将它们拉回内部。不知道这意味着什么,但是我认为更多信息不会受到伤害。

附录
https://security.stackexchange.com/questions/167064/is-csrf-protection-useless-with-ajax/167076#167076

最佳答案

我的回答将建议不要尝试基于AJAX调用中的 token 使用CSRF保护,而应依赖于Web浏览器的 native CORS功能。

基本上,从浏览器到后端服务器的任何AJAX调用都将检查域的来源(也就是加载脚本的域)。如果这些域匹配(JS托管域==目标AJAX服务器域),则AJAX调用会正常执行,否则返回null

如果攻击者尝试在自己的服务器上托管恶意AJAX查询,则如果您的后端服务器没有允许他这样做的CORS策略,则该攻击将会失败(默认情况下就是这种情况)。

因此,就 native 而言, CSRF保护在AJAX调用中是无用的,您可以通过不尝试处理来降低的技术债务。

有关CORS - Mozilla Foundation的更多信息

代码示例-使用控制台检查器!

<html>
<script>
function reqListener () {
  console.log(this.responseText);
}

var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener);
oReq.open("GET", "http://www.reuters.com/");
oReq.send();
</script>
</html>


运行它并查看安全性错误:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://www.reuters.com/. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).



Mozilla对于Cross-site XMLHttpRequest实现非常清楚:

Modern browsers support cross-site requests by implementing the Web Applications (WebApps) Working Group's Access Control for Cross-Site Requests standard.

As long as the server is configured to allow requests from your web application's origin, XMLHttpRequest will work. Otherwise, an INVALID_ACCESS_ERR exception is thrown.

关于asp.net - 使用WebApi时,防伪Cookie token 和表单字段 token 不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45389512/

相关文章:

asp.net-mvc - Microsoft ASP .NET Web API,MVC 4和SPA体系结构

asp.net-mvc-4 - MVC 4 Web Api 在 x64 模式下构建,在执行 "Could not load file or assembly ' xxx' 或其依赖项之一时出错

c# - 基于 Switch 枚举将对象转换到 WebControl?

c# - 如何在网络技术上制作特定日期和时间的倒计时器

c# - 正在解析的 MVC 4 详细信息页面 2 个 id

c# - 实体类型 ApplicationUser 不是当前上下文 Asp.Net MVC 模型的一部分

c# - SignalR .NET 客户端在第一次连接尝试时抛出 TimeoutException

asp.net-mvc - 为 asp.net mvc 应用程序托管 MS Windows Workflow 运行时的良好做法是什么?

asp.net-mvc - ASP.NET MVC Controller 单元测试令人困惑

c# - 从 asp.net web api 下载文件