【问题标题】:Web API Antiforgery Tokens are swapped交换了 Web API 防伪令牌
【发布时间】:2017-12-29 14:11:17
【问题描述】:

我的 Web API 由 Node 进程中托管的 Angular 客户端访问,因此我正在生成防伪令牌作为 OAuth 令牌生成的一部分,并将它们作为 cookie 附加到响应中,如下所示:

public static void SetXsrfCookies(IOwinResponse response, DateTime expiresUtc)
    {
        string cookieToken;
        string formToken;

        AntiForgery.GetTokens("", out cookieToken, out formToken);

        response.Cookies.Append(AntiForgeryConfig.CookieName, cookieToken,
            new CookieOptions()
            {
                HttpOnly = true /* we want JavaScript clients to read this cookie*/,
                Expires = expiresUtc
            });

        response.Cookies.Append("FORM-TOKEN", formToken,
            new CookieOptions()
            {
                HttpOnly = true /* we want JavaScript clients to read this cookie*/,
                Expires = expiresUtc
            });
    }

我看到客户端正在接收 cookie。

然后对于后续调用,我包括以下标题:

Authorization: Bearer someOAuthToken
Content-Type: application/json
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36     (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36
Cache-Control: no-cache
__RequestVerificationToken: someCookieToken
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
Cookie: Logout=true; __RequestVerificationToken=someFormToken

可以注意到,我在标题中包含了 cookieToken 和 formToken。

当客户拨打电话时,我会验证这些令牌,如下所示(此代码根据其他 SO 人的讨论):

var headers = actionContext.Request.Headers;
var cookie = headers.GetCookies()
                    .Select(c => c[AntiForgeryConfig.CookieName])
                    .FirstOrDefault();
var aspNetMvcRequestVerificationToken = headers.GetValues(AntiForgeryConfig.CookieName).FirstOrDefault();
AntiForgery.Validate(cookie != null ? cookie.Value : null,  aspNetMvcRequestVerificationToken);

此方法失败并出现以下错误

“验证提供的防伪令牌失败。cookie“__RequestVerificationToken”和表单字段“__RequestVerificationToken”已交换。”

在此之后,我尝试交换但出现以下错误:

“所提供的防伪令牌适用于与当前用户不同的基于声明的用户。”

我看到很少有人报告类似错误:link 但不确定解决方案。有人可以查看上面的代码并让我知道错误。

注意:我使用 Fiddler 进行测试。

谢谢

【问题讨论】:

    标签: cookies asp.net-web-api antiforgerytoken


    【解决方案1】:

    这是由于您的静态函数调用而发生的

    public static void SetXsrfCookies(IOwinResponse response, DateTime expiresUtc)
    

    要么从函数中删除静态属性,要么更好地将函数用作异步任务

    public async static void SetXsrfCookies(IOwinResponse response, DateTime expiresUtc)
        {
            string cookieToken;
            string formToken;
    
            AntiForgery.GetTokens("", out cookieToken, out formToken);
    
            response.Cookies.Append(AntiForgeryConfig.CookieName, cookieToken,
                new CookieOptions()
                {
                    HttpOnly = true /* we want JavaScript clients to read this cookie*/,
                    Expires = expiresUtc
                });
    
           await response.Cookies.Append("FORM-TOKEN", formToken,
                new CookieOptions()
                {
                    HttpOnly = true /* we want JavaScript clients to read this cookie*/,
                    Expires = expiresUtc
                });
        } 
    

    当多个用户根据负载调用相同的函数并调用 id 交换时,我遇到了与 webmethod (aspx) 相同的问题,将静态函数更改为动态函数,希望这对你也有用

    【讨论】:

    • 与静态无关(我已更改代码并测试以确认这一点)。此外,它与任何负载无关,因为我只与一个用户进行开发人员测试。我相信一定有其他东西帮助了你:-)
    • 你在等待response.Cookies.Append吗?
    【解决方案2】:

    我检查了你的代码,发现了一些问题。

    1. 你在请求头中设置了someCookieToken,在cookie中设置了someFormToken,所以你确实错误的交换了cookie token和form token。您应该在 cookie 中设置 someCookieToken,并在请求标头中设置 someFormToken
    2. 您使用AntiForgery.GetTokens方法创建cookie令牌和表单令牌,我只找到您将它们添加到Cookies中的代码,但找不到您如何设置的代码__RequestVerificationToken 进入请求头。所以我认为您在请求中添加的 cookie 令牌和表单令牌不是正确的一对。

    【讨论】:

      【解决方案3】:

      在您的代码行"__RequestVerificationToken=someFormToken" 中,将其更改为"RequestVerificationToken" 或其他名称。由于表单令牌和 cookie 令牌都具有相同的名称 "__RequestVerificatioToken",因此您会收到错误消息。

      【讨论】:

        猜你喜欢
        • 2014-10-03
        • 1970-01-01
        • 2018-04-13
        • 2018-07-11
        • 1970-01-01
        • 2015-01-11
        • 2018-01-02
        • 2019-03-05
        • 2018-01-16
        相关资源
        最近更新 更多