AntiforgeryValidationException:提供的防伪令牌适用于与当前用户不同的基于声明的用户

Jon*_*gel 7 asp.net-mvc asp.net-core-mvc asp.net-core

我不确定这里发生了什么,但我在我的cookie中看到了2个不同的令牌.一个是"XSRF-TOKEN",另一个是".AspNetCore.Antiforgery.OnvOIX6Mzn8",它们具有不同的值.

我正在使用ASP.Net Core 2.1,SPA设置(和前端的Angular),我在Startup.cs中有以下内容.

我不知道是什么创建后一个令牌,因为它似乎不是我添加的任何代码.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IAntiforgery antiforgery)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler(
            builder =>
            {
            builder.Run(
                async context =>
                {
                context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                context.Response.Headers.Add("Access-Control-Allow-Origin", "*");

                var error = context.Features.Get<IExceptionHandlerFeature>();
                if (error != null)
                {
                    context.Response.AddApplicationError(error.Error.Message);
                    await context.Response.WriteAsync(error.Error.Message).ConfigureAwait(false);
                }
                });
            });
    }

    app.UseAuthentication();
    app.UseHttpsRedirection();
    app.UseDefaultFiles();
    app.UseStaticFiles();
    app.UseJwtTokenMiddleware();
    app.UseSpaStaticFiles();
    app.UseCookiePolicy();

    app.UseMvc(routes =>
    {
            routes.MapRoute(
                name: "default",
                template: "{controller}/{action=Index}/{id?}");
        });

        app.UseSpa(spa =>
        {
            spa.Options.SourcePath = "ClientApp";
            spa.UseSpaPrerendering(options =>
            {
                options.BootModulePath = $"{spa.Options.SourcePath}/dist/server/main.js";
                options.BootModuleBuilder = env.IsDevelopment()
                    ? new AngularCliBuilder(npmScript: "build:ssr")
                    : null;
                options.ExcludeUrls = new[] { "/sockjs-node" };
            });

            if (env.IsDevelopment())
            {
                spa.UseAngularCliServer(npmScript: "start");
            }
        });

        app.UseMiddleware<AntiForgeryMiddleware>("XSRF-TOKEN");
    }
}

public static class ApplicationBuilderExtensions
{
    public static IApplicationBuilder UseAntiforgeryTokenMiddleware(this IApplicationBuilder builder, string requestTokenCookieName)
    {
        return builder.UseMiddleware<AntiForgeryMiddleware>(requestTokenCookieName);
    }
}

public class AntiForgeryMiddleware
{
    private readonly RequestDelegate next;
    private readonly string requestTokenCookieName;
    private readonly string[] httpVerbs = new string[] { "GET", "HEAD", "OPTIONS", "TRACE" };

public AntiForgeryMiddleware(RequestDelegate next, string requestTokenCookieName)
{
    this.next = next;
    this.requestTokenCookieName = requestTokenCookieName;
}

public async Task Invoke(HttpContext context, IAntiforgery antiforgery)
{
    if (httpVerbs.Contains(context.Request.Method, StringComparer.OrdinalIgnoreCase))
    {
        var tokens = antiforgery.GetAndStoreTokens(context);

        context.Response.Cookies.Append(requestTokenCookieName, tokens.RequestToken, new CookieOptions()
        {
            HttpOnly = false
        });
    }

    await next.Invoke(context);
}
Run Code Online (Sandbox Code Playgroud)

}

Sal*_*Sal 1

默认情况下,AspNetCore 使用“AspNetCore.AntiForgery.XXX”(除非由您的配置重命名)创建一个 cookie,以防止 xsrf/csrf 攻击。

我还在这篇MSDN 文章中读到,AngularJS 也有一种自动处理 xsrf/csrf 场景的方法:

AngularJS 使用约定来解决 CSRF。如果服务器发送名为 XSRF-TOKEN 的 cookie,则 AngularJS $http 服务在向服务器发送请求时会将 cookie 值添加到标头中。这个过程是自动的。不需要显式设置标头。标头名称为 X-XSRF-TOKEN。服务器应该检测此标头并验证其内容。对于 ASP.NET Core API,请使用此约定:配置您的应用程序以在名为 XSRF-TOKEN 的 cookie 中提供令牌。配置防伪服务以查找名为 X-XSRF-TOKEN 的标头。

services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");

您的应用程序是否配置为同时生成默认的 AntiForgery cookie 和 XSRF-TOKEN?如果是这种情况,您可能会生成并接收两个不同的防伪令牌,这可能会导致问题