C# 为什么AntiForgeryToken验证一直失败?

C# 为什么AntiForgeryToken验证一直失败?,c#,asp.net-core-2.0,csrf-protection,antiforgerytoken,C#,Asp.net Core 2.0,Csrf Protection,Antiforgerytoken,我正在开发一个webAPI应用程序,使用asp.net core2和Angular运行。详细的开发环境配置如下所示。 我正在尝试配置AntiForgeryToken验证,但一直失败。我遵循了配置,但是我不得不修改它,因为我的angular应用程序和asp.net服务器在两个不同的端口上运行,因为前端启动程序没有生成令牌。我通过调用app组件ngOnInit上的API路径(/API/Account/ContactInitialization)启动后端,该路径允许我生成令牌。 配置如下所示 ISer

我正在开发一个web
API
应用程序,使用
asp.net core2
Angular
运行。详细的开发环境配置如下所示。 我正在尝试配置
AntiForgeryToken
验证,但一直失败。我遵循了配置,但是我不得不修改它,因为我的angular应用程序和asp.net服务器在两个不同的端口上运行,因为前端启动程序没有生成令牌。我通过调用app组件
ngOnInit
上的
API
路径(
/API/Account/ContactInitialization
)启动后端,该路径允许我生成令牌。 配置如下所示

IServiceCollection
服务:

        services.AddAntiforgery(options =>
                {
                    options.HeaderName = "X-CSRF-TOKEN";
                    options.SuppressXFrameOptionsHeader = false;
                });
IApplicationBuilder配置中:

app.Use(next => context =>
                {
                    string path = context.Request.Path.Value;
                    if (

                        string.Equals(path, "/", StringComparison.OrdinalIgnoreCase) ||
                        string.Equals(path, "/api/Account/ContactInitialization", StringComparison.OrdinalIgnoreCase) ||
                        string.Equals(path, "/index.html", StringComparison.OrdinalIgnoreCase))
                    {
                        // We can send the request token as a JavaScript-readable cookie, 
                        // and Angular will use it by default.
                         var tokens = antiforgery.GetAndStoreTokens(context);
                        context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken,
                            new CookieOptions() { HttpOnly = false });
                    }

                    return next(context);
                });
asp.net。生成两组密钥

我用
[ValidateAntiForgeryToken]
修饰了我的方法,并在我的头请求中包含
XSRF-TOKEN
cookie内容。然而,在调用
API
之后,我一直收到
400(错误请求)
响应!我错过了什么

控制器方法

    [Authorize]
    [ValidateAntiForgeryToken]
    [HttpPost]
    public IEnumerable<string> AutherizeCookie()
    {
        return new string[] { "Hello", "Auth Cookie" };
    }
[授权]
[ValidateAntiForgeryToken]
[HttpPost]
公共IEnumerable AutherizeCookie()
{
返回新字符串[]{“Hello”,“Auth Cookie”};
}
我的详细标题请求如下所示


我想你可能遵循了,但掩盖了相关的部分。到目前为止,您所做的工作仅适用于Angular,因为Angular的
$http
实际上会基于
XSRF-TOKEN
cookie添加
X-XSRF-TOKEN
头。(但是,请注意,即使如此,您还是将标题设置为
X-CSRF-TOKEN
,这在这里实际不起作用。它必须是
X-XSRF-TOKEN

但是,如果您没有使用Angular,那么您需要自己在AJAX请求中设置头,这可能是您忽略的。在这种情况下,您实际上不需要更改任何antiforgery令牌配置(头名称、设置cookie等)。您只需提供标题作为
RequestVerificationToken
。例如,使用jQuery:

$.ajax({
    ...
    headers:
    {
        "RequestVerificationToken": '@GetAntiXsrfRequestToken()'
    },
    ...
});
这将适用于视图中的JavaScript。如果需要在外部JS中执行此操作,则需要设置cookie,以便可以从cookie中获取值。除此之外,同样的方法也适用


如果您只是想更改标题名称,您可以这样做;您只需将此处的
RequestVerificationHeader
部分更改为相同的值。

谢谢,@Chris\u Pratt指出我遇到的标题问题。然而,为了明确起见,我还有其他问题将在下面讨论

我的
CORS
配置错误,我的工作代码如下:

services.AddCors(options =>
            {
                options.AddPolicy("CorsPolicy",
                    builder => builder
                        .WithOrigins("https://www.artngcore.com:4200") //Note:  The URL must be specified without a trailing slash (/).
                        .AllowAnyMethod()
                        .AllowAnyHeader()
                        .AllowCredentials());
            });

            services.AddAntiforgery(options =>
                {
                    options.HeaderName = "X-XSRF-TOKEN";
                    options.SuppressXFrameOptionsHeader = false;
                });  
中间件
配置是

app.Use(next => context =>
               {
                   string path = context.Request.Path.Value;
                   var tokens = antiforgery.GetAndStoreTokens(context);
                   context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken,
                        new CookieOptions() { HttpOnly = false, 
Secure = true // set false if not using SSL });
                   return next(context);
               });
在控制器中

[Route("/api/[controller]/[action]")]
[EnableCors("CorsPolicy")]
public class AccountController : ArtCoreSecuredController ....
这里的诀窍是,令牌必须在身份验证后刷新。仅在身份验证(登录)后调用API即可。 别忘了在请求中添加以下标题

 const headers = new HttpHeaders({
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${this.cookieService.get('ArtCoreToken')}`,
            'X-XSRF-TOKEN': `${this.cookieService.get('XSRF-TOKEN')}`
        });
i、 e

[HttpGet]
[异名]
公共异步任务刷新令牌()
{
等待任务。延迟(1);
返回状态码(200);
} 

这就是我的工作。希望能有所帮助。

您需要使用credentials=true发出XHR请求,这将使浏览器设置cookie,否则您将收到400个错误请求,因为cookie不存在,并且X-XSRF-TOKEN未设置或设置为空字符串。

我使用Angular,它默认情况下会像您所说的那样附加cookie。我将提供的令牌头更改为
X-XSRF-Token
,但仍然得到相同的响应,代码如下所示
services.AddAntiforgery(options=>{options.HeaderName=“X-XSRF-Token”;})和<代码>var令牌=antiforgery.GetAndStoreTokens(上下文);context.Response.Cookies.Append(“X-XSRF-TOKEN”,tokens.RequestToken,…
我没有把这篇文章写得太长,但是我已经发布了我的启动配置,在我的代码中,我把我的标题改为
X-XSRF-TOKEN
cookie名称应该是
XSRF-TOKEN
改为
var tokens=antiforgery.GetAndStoreTokens(context);context.Response.Cookies.Append(“XSRF-TOKEN”,tokens.RequestToken
,我将标题保留为
X-XSRF-TOKEN
,不起作用,我希望我收到错误,只有400个错误的request.LGTM。尝试从中间件中删除
if
条件?如果你的意思是,我在生成令牌方面没有问题,否则请解释为什么我没有删除该条件了解为什么应该进行RefreshToken调用?是因为CORS吗?对我来说,情况基本相同,只是我没有启用CORS,我需要注销并再次登录我的webapp才能进行调用。请参考此问题,根据设计,密钥必须在验证后刷新。嗯,我对此没有什么疑问。不使用
ValidateAntiForegeryToken
表示您的控制器实际上没有验证csrf令牌,而只是检查CORS策略?编辑:实际上刚刚测试了这一点;我从前端删除了实际的csrf令牌(请求发送的是后端未提供的伪csrf令牌),并且它允许请求
    [HttpGet]
    [AllowAnonymous]
    public async Task<IActionResult> RefreshToken()
    {
        await Task.Delay(1);

        return StatusCode(200);

    }