asp.net - 所提供的防伪 token 验证失败。 cookie token 和请求 token 已交换

标签 asp.net asp.net-core .net-core asp.net-core-2.0

我使用 IAntiforgery API 创建了一个 ASP.Net Core 2 应用程序。

这提供了一种返回 cookie 的方法。

客户端获取该 cookie,并在后续 POST 请求中将该值放入 X-XSRF-TOKEN header 中。

中间件会验证这一点,并在请求失败时允许请求继续或不允许。

在请求中发送正确的 cookie 和 header 时,验证总是失败,我不明白为什么。

完整复制品在这里 https://github.com/jchannon/AntiForgery

但是,主要问题区域如下。

public class Startup
{
    public void Configure(IApplicationBuilder app, IAntiforgery antiforgery, ILoggerFactory loggerFactory)
    {
        app.UseAuthentication();

        app.Use(async (context, next) =>
        {
            var logger = loggerFactory.CreateLogger("ValidRequestMW");

            //Don't validate POST for login
            if (context.Request.Path.Value.Contains("login"))
            {
                await next();
                return;
            }

            logger.LogInformation(context.Request.Cookies["XSRF-TOKEN"]);
            logger.LogInformation(context.Request.Headers["X-XSRF-TOKEN"]);

            //On POST requests it will validate the XSRF header
            if (!await antiforgery.IsRequestValidAsync(context))
            {

                /****************************************************
                 *
                 *
                 * For some reason when the cookie and the header are sent in on the /create POST this validation always fails
                 * 
                 * 
                 ***************************************************/
                context.Response.StatusCode = 401;

                logger.LogError("INVALID XSRF TOKEN");
                return;
            }
            await next();
        });

        app.UseRouter(r =>
        {
            r.MapGet("", async context => { await context.Response.WriteAsync("hello world"); });

            //This returns a XSRF-TOKEN cookie
            //Client will take this value and add it as a X-XSRF-TOKEN header and POST to /create
            r.MapPost("login", async (context) =>
            {
                antiforgery.SetCookieTokenAndHeader(context);
                context.Response.Redirect("/");
            });

            //If XSRF validaiton is correct we should hit this route
            r.MapPost("create", async context =>
            {
                context.Response.StatusCode = 201;
                await context.Response.WriteAsync("Created");
            });
        });
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddLogging(x => x.AddConsole());

        services.AddAntiforgery(options =>
        {
            options.HeaderName = "X-XSRF-TOKEN";
            options.Cookie.Name = "XSRF-TOKEN";
            options.Cookie.HttpOnly = false;
        });

//        services.AddAuthentication("MyCookieMW")
//                .AddCookie("MyCookieMW", cookieOptions =>
//                {
//                    cookieOptions.Cookie.Name = "MyCookie";
//                    cookieOptions.Cookie.HttpOnly = true;
//                    cookieOptions.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
//                    cookieOptions.SlidingExpiration = true;
//                });

        services.AddRouting();
    }
}

最佳答案

因此,在深入研究防伪源代码和一些命名不当的方法之后(SetCookieTokenAndHeader,我正在看着你)。正确的代码应该是:

    public void Configure(IApplicationBuilder app, IAntiforgery antiforgery, ILoggerFactory loggerFactory)
    {
        app.Use(async (context, next) =>
        {
            var logger = loggerFactory.CreateLogger("ValidRequestMW");

            //Don't validate POST for login
            if (context.Request.Path.Value.Contains("login"))
            {
                await next();
                return;
            }

            logger.LogInformation("Request Cookie is " + context.Request.Cookies["XSRF-TOKEN"]);
            logger.LogInformation("Request Header is " + context.Request.Headers["X-XSRF-TOKEN"]);

            //On POST requests it will validate the XSRF header
            if (!await antiforgery.IsRequestValidAsync(context))
            {
                context.Response.StatusCode = 401;

                logger.LogError("INVALID XSRF TOKEN");
                return;
            }
            await next();
        });

        app.UseRouter(r =>
        {
            r.MapGet("", async context => { await context.Response.WriteAsync("hello world"); });

            //This returns a XSRF-TOKEN cookie
            //Client will take this value and add it as a X-XSRF-TOKEN header and POST to /create
            r.MapPost("login", async (context) =>
            {
                var tokens = antiforgery.GetAndStoreTokens(context);
                context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, 
                    new CookieOptions() { HttpOnly = false });
                context.Response.Redirect("/");
            });

            //If XSRF validaiton is correct we should hit this route
            r.MapPost("create", async context =>
            {
                context.Response.StatusCode = 201;
                await context.Response.WriteAsync("Created");
            });
        });
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<IAntiforgeryTokenGenerator, MyTokenGenerator>();
        services.AddSingleton<IAntiforgery, MyAntiforgery>();

        services.AddLogging(x => x.AddConsole());

        services.AddAntiforgery(options =>
        {
            options.HeaderName = "X-XSRF-TOKEN";
            options.Cookie.Name = "MyAntiforgery";
            options.Cookie.HttpOnly = false;
        });

        services.AddRouting();
    }

关于asp.net - 所提供的防伪 token 验证失败。 cookie token 和请求 token 已交换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47052850/

相关文章:

c# - ASP.NET网页.aspx.cs文件中的私有(private)静态变量

linux - 无法启动红est。 System.IO.IOException : Failed to bind to address http://127.0.0.1:5000: address already in use

.net - 你如何在 .NET Core 中获得 post 值

c# - 更改 WebAPI 中的默认路由

c# - 从 C# 中的 cmd.Parameters 获取 ReturnValue?

c# - 协助重构 LINQ 方法

xml - 返回 "application/xml"而不是 "text/plain"ASP.NET Core Web API

c# - 模型绑定(bind)的复杂类型不能是抽象类型或值类型,并且必须具有无参数构造函数

c# - 如何在 N 层架构中使用 ASP.NET Core 应用程序使用 EF Core DBContext?

c# - .net 中的 JWT 生成和验证抛出 "Key is not supported"