AntiForgeryToken Expiration Blank Page

后端 未结 3 1524
情书的邮戳
情书的邮戳 2021-02-20 03:17

I\'m using IdentityServer4 with ASP.NET Core 2.2. On the Post Login method I have applied the ValidateAntiForgeryToken. Generally after 20 minutes to 2 hours of sitting on the l

3条回答
  •  一个人的身影
    2021-02-20 03:30

    Update '2021

    Since ASP.Net Core 3.0 MS decided to make ValidateAntiforgeryTokenAuthorizationFilter internal. Now we have to copy-paste their code, to be able to derive. But most likely we don't need to. To just change the resulting behavior all we need is to test the context for the IAntiforgeryValidationFailedResult and proceed accordantly, as described in this example.

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.Core.Infrastructure;
    using Microsoft.AspNetCore.Mvc.Filters;
    
    namespace BasicWebSite.Filters
    {
        public class RedirectAntiforgeryValidationFailedResultFilter : IAlwaysRunResultFilter
        {
            public void OnResultExecuting(ResultExecutingContext context)
            {
                if (context.Result is IAntiforgeryValidationFailedResult result)
                {
                    context.Result = 
                        new RedirectResult("http://example.com/antiforgery-redirect");
                }
            }
    
            public void OnResultExecuted(ResultExecutedContext context)
            { }
        }
    }
    

    Then within the controller:

    // POST: /Antiforgery/LoginWithRedirectResultFilter
    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    [TypeFilter(typeof(RedirectAntiforgeryValidationFailedResultFilter))]
    public string LoginWithRedirectResultFilter(LoginViewModel model)
    {
        return "Ok";
    }
    

    The original answer covering .net core 2.2

    Yet another implementation using the default one including all prechecks, logging etc. And it's still an AuthorizationFilter, so that prevents any further action execution. The only difference is that it triggers HttpGet to the same url instead of the default 400 response, a kind of the Post/Redirect/Get pattern implementation.

    public class AnotherAntiForgeryTokenAttribute : TypeFilterAttribute
    {
        public AnotherAntiForgeryTokenAttribute() : base(typeof(AnotherAntiforgeryFilter))
        {
        }
    }
    
    
    public class AnotherAntiforgeryFilter:ValidateAntiforgeryTokenAuthorizationFilter,
        IAsyncAuthorizationFilter
    {
        public AnotherAntiforgeryFilter(IAntiforgery a, ILoggerFactory l) : base(a, l)
        {
        }
    
        async Task IAsyncAuthorizationFilter.OnAuthorizationAsync(
            AuthorizationFilterContext ctx)
        {
            await base.OnAuthorizationAsync(ctx);
    
            if (ctx.Result is IAntiforgeryValidationFailedResult)
            {
                // the next four rows are optional, just illustrating a way
                // to save some sensitive data such as initial query
                // the form has to support that
                var request = ctx.HttpContext.Request;
                var url = request.Path.ToUriComponent();
                if (request.Form?["ReturnUrl"].Count > 0)
                    url = $"{url}?ReturnUrl={Uri.EscapeDataString(request.Form?["ReturnUrl"])}";
    
                // and the following is the only real customization
                ctx.Result = new LocalRedirectResult(url);
            }
        }
    }
    

提交回复
热议问题