在ASP.NET Core AntiforgeryTokenSet中,RequestToken和CookieToken的用法有什么区别?

时间:2019-10-04 13:45:02

标签: angular asp.net-core csrf

我们有一个带有Cookie身份验证的Angular SPA的ASP.NET Core 2.2 Web应用程序。

我正在按照configure antiforgery features with IAntiforgery的说明进行操作。

相关代码段为:

services.AddAntiforgery();
public void Configure(IApplicationBuilder app, IAntiforgery antiforgery)
{
    app.Use(next => context =>
    {
        string path = context.Request.Path.Value;

        if (
            string.Equals(path, "/", StringComparison.OrdinalIgnoreCase) ||
            string.Equals(path, "/index.html", StringComparison.OrdinalIgnoreCase))
        {
            // The request token can be sent as a JavaScript-readable cookie, 
            // and Angular uses it by default.
            var tokens = antiforgery.GetAndStoreTokens(context);
            context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, 
                new CookieOptions() { HttpOnly = false });
        }

        return next(context);
    });
}

antiforgery.GetAndStoreTokens(context)的调用返回一个AntiforgeryTokenSet,它具有RequestTokenCookieToken属性。

如果我在默认配置下使用上述代码,则会得到两个cookie:.AspNetCore.Antiforgery.*(匹配CookieToken)和XSRF-TOKEN(匹配RequestToken),它们的值不同

RequestTokenCookieToken之间的用法有什么区别

2 个答案:

答案 0 :(得分:1)

XSRF-TOKEN

这是Angular应用程序将读取并作为HTTP标头发送回的JavaScript可读cookie。

.AspNetCore.Antiforgery.*

这是仅用于HTTP的cookie(即 JavaScript可读),将由浏览器作为典型的cookie发送回服务器。


ASP.NET Core中的CSRF保护要求同时发送HTTP标头和cookie。验证请求时,它将同时检查标头和cookie。如果缺少任何一个,验证将失败。

答案 1 :(得分:1)

有两个cookie的原因是ASP.NET Core使用Double Submit Cookie中所述的OWASP Cross-Site Request Forgery (CSRF) Cheat Sheet模式。

这篇出色的文章ASP.NET Core CSRF defence with AntiforgeryMicrosoft documentation更详细地描述了该过程:


  

...它提供了一种无状态防御机制,该机制由2个项目(或令牌集)组成,应在Antiforgery软件包验证的任何请求中找到:

     
      
  • 包含在cookie中的防伪令牌,作为伪随机值生成并使用新的Data Protection API加密

  •   
  • 包含为表单字段,标题或cookie的附加令牌。其中包括相同的伪随机值,以及来自当前用户身份的其他数据。还可以使用Data Protection API对其进行加密。

  •   
     

这些令牌将在服务器端生成,并与html文档一起传播到用户的浏览器。当浏览器发送新请求时,默认情况下将包含cookie令牌,而应用程序需要确保也包含该请求令牌。 (我们将在下一部分中看到如何执行此操作)

     

在以下情况下,请求将被拒绝

:      
      
  • 两个令牌中的任何一个都不存在或格式/加密不正确
  •   
  • 它们的伪随机值不同
  •   
  • 第二个令牌中嵌入的用户数据与当前经过身份验证的用户不符
  •   

  

对于Angular,您将使用其$ http服务发送AJAX请求。如果此服务可以找到标记值为XSRF-TOKEN的cookie作为令牌,则该服务将自动包含名称为X-XSRF-TOKEN的标头。因此,最简单的方法是按照Angular希望我们的方式进行操作,并创建一些将获取请求令牌的中间件,并将其值存储为XSRF-TOKEN cookie。

     

即使将其添加为cookie,它仍然是请求令牌,而不是cookie令牌!这听起来可能令人困惑,所以让我尝试澄清一下:

     

应用程序会将带有请求令牌的cookie XSRF-TOKEN和带有cookie令牌的另一个cookie .AspNetCore.Antiforgery。*发送回浏览器。   每当Angular发送Ajax请求时,请求将包括带有请求令牌的标头X-XSRF-TOKEN和带有cookie令牌的cookie .AspNetCore.Antiforgery。*。   防伪验证将确保两个令牌均有效并且共享相同的机密信息,等等。


因此应该有两个cookie。在我的场景中,随每个请求发送的.AspNetCore.Antiforgery.* cookie构成了令牌集的一半,然后Angular使用XSRF-TOKEN来设置X-XSRF-TOKEN头,令牌集的另一半。


另请参阅: