Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
696 views
in Technique[技术] by (71.8m points)

csrf - ValidateAntiForgeryToken in an ASP.NET Core React SPA Application

I'm trying to use the framework's tools to add some simple CSRF validation to an ASP.NET Core React SPA. The application itself is essentially a create-react-app setup (a single index.html with a root element and everything else is loaded in from bundled JavaScript).

Tinkering with some information found on links such as this one, I've set the following in my Startup.ConfigureServices:

services.AddAntiforgery(options => options.Cookie.Name = "X-CSRF-TOKEN");

And confirmed in my Chrome tools that the cookie is being set. If I omit the above line, a cookie is still set with a partially randomized name, such as: .AspNetCore.Antiforgery.RAtR0X9F8_w Either way the cookie is being set. I've also confirmed that any time I re-start the whole application the cookie value is updated, so the framework is actively setting this cookie.

Observing network requests in my Chrome tools, I confirm that the cookie is being sent to the server on AJAX request. Placing a breakpoint on the server and observing the Request.Cookies value in a controller action also confirms this.

However, if I decorate any such AJAX requested action with [ValidateAntiForgeryToken] then the response is always an empty 400.

Is there a configuration step I've missed somewhere? Perhaps the action attribute is looking in the wrong place and I need to use a different validation?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I just inspect the log and find out there's an exception:

Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException: The required antiforgery cookie ".AspNetCore.Antiforgery.HPE6W9qucDc" is not present. at Microsoft.AspNetCore.Antiforgery.Internal.DefaultAntiforgery.ValidateRequestAsync(HttpContext httpContext) at Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.ValidateAntiforgeryTokenAuthorizationFilter.OnAuthorizationAsync(AuthorizationFilterContext context)

It indicates that you forgot to configure the cookie name :

   public void ConfigureServices(IServiceCollection services)
   {
       //services.AddAntiforgery();
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

       // In production, the React files will be served from this directory
       services.AddSpaStaticFiles(configuration =>
       {
           configuration.RootPath = "ClientApp/build";
       });
   }

So I just add a configuration as below :

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAntiforgery(o => {
            o.Cookie.Name = "X-CSRF-TOKEN";
        });
        // ...
    }

and it works now.

Also, if you would like to omit the line of services.AddAntiforgery(options => options.Cookie.Name = "X-CSRF-TOKEN"); , you can use the built-in antiforgery.GetAndStoreTokens(context) method to send cookie:

   app.Use(next => context =>
    {
        if (context.Request.Path == "/")
        {
            //var tokens = antiforgery.GetTokens(context);
            var tokens = antiforgery.GetAndStoreTokens(context);
            context.Response.Cookies.Append("X-CSRF-TOKEN", tokens.CookieToken, new CookieOptions { HttpOnly = false });
            context.Response.Cookies.Append("X-CSRF-FORM-TOKEN", tokens.RequestToken, new CookieOptions { HttpOnly = false });
        }
        return next(context);
    })

Both should work as expected.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...