为什么AntiForgeryToken验证会失败?

时间:2017-12-31 00:19:18

标签: c# asp.net-core-2.0 csrf-protection antiforgerytoken

我正在开发使用APIasp.net core2投放的网络Angular应用。详细的开发环境配置为here。 我正在尝试配置AntiForgeryToken验证,但它仍然失败。我按照配置。 here,但我必须修改它,因为我的角度应用程序和asp.net服务器在两个不同的端口上运行,因为前端启动不会生成令牌。我通过在应用组件API上调用/api/Account/ContactInitialization路径(ngOnInit)来启动后端,这允许我生成令牌。 配置如下所示,

IServiceCollection服务:

        services.AddAntiforgery(options =>
                {
                    options.HeaderName = "X-CSRF-TOKEN";
                    options.SuppressXFrameOptionsHeader = false;
                });

IApplicationBuilder Configure

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。生成两组密钥,

enter image description here

我使用[ValidateAntiForgeryToken]修饰了我的方法,并在标头请求中包含了XSRF-TOKEN Cookie内容。但在致电400 (Bad Request)后我仍然收到API回复!我在这里错过了什么?

控制器方法,

    [Authorize]
    [ValidateAntiForgeryToken]
    [HttpPost]
    public IEnumerable<string> AutherizeCookie()
    {
        return new string[] { "Hello", "Auth Cookie" };
    }

我的详细标题请求如下所示,

Header Request

3 个答案:

答案 0 :(得分:4)

我假设你可能跟随documentation,但是掩盖了相关的位。到目前为止您所做的只适用于Angular,因为Angular的$http实际上会根据X-XSRF-TOKEN Cookie添加XSRF-TOKEN标头。 (但是,请注意,即使这样,您也可以将标题设置为X-CSRF-TOKEN,但这实际上不会在这里工作。它必须是X-XSRF-TOKEN)。

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

$.ajax({
    ...
    headers:
    {
        "RequestVerificationToken": '@GetAntiXsrfRequestToken()'
    },
    ...
});

这将适用于JavaScript。如果你需要在外部JS中执行此操作,那么您需要设置cookie,以便您可以从cookie中获取值。除此之外,适用相同的方法。

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

答案 1 :(得分:1)

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

答案 2 :(得分:0)

谢谢,@ Chris_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;
                });  

middleware配置是,

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')}`
        });

    [HttpGet]
    [AllowAnonymous]
    public async Task<IActionResult> RefreshToken()
    {
        await Task.Delay(1);

        return StatusCode(200);

    } 

这对我有用。希望它有所帮助。