AntiForgeryToken到期空白页

时间:2019-05-24 14:52:15

标签: c# asp.net-core identityserver4 antiforgerytoken

我正在使用IdentityServer4和ASP.NET Core 2.2。在Post Login方法上,我应用了ValidateAntiForgeryToken。通常,在坐在登录页面上20分钟到2个小时之后,尝试登录时会生成空白页面。

如果您查看Postman Console,则会收到一条400错误的请求消息。然后,我将AntiForgery选项上的Cookie有效期设置为90天。我能够让该页面坐满6个小时,并且仍然可以登录。但是,大约8个小时(过夜)后,尝试登录后我又收到了空白页。

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login
services.AddAntiforgery(options =>
{
    options.Cookie.Expiration = TimeSpan.FromDays(90);
});

我希望能够在登录页面上停留90天,这是cookie的持续时间,但这是行不通的。如何获得AntiforgeryToken的Cookie可以持续整整90天或我设置的任何时间,而不是超时或过期?有没有办法捕获此错误并将用户重定向回登录方法?

3 个答案:

答案 0 :(得分:3)

这是我的最终解决方案。我使用IAntifogery依赖项注入添加了一个属性。

public class CustomValidationAttribute : ActionFilterAttribute
{
    private IAntiforgery _antiForgery { get; }

    public CustomValidationAttribute(IAntiforgery antiforgery)
    {
        _antiForgery = antiforgery;
    }

    public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        var isRequestValid = await this._antiForgery.IsRequestValidAsync(context.HttpContext);
        if (!isRequestValid)
        {
            //Add Code here if token is not valid

            return;         
        }

        await next();
    }
}

将属性添加到还使用[HttpPost]的控制器方法中

[TypeFilter(typeof(CustomValidationAttribute))]

答案 1 :(得分:1)

另一种使用默认实现的实现,包括所有预检查,日志记录等。它仍然是AuthorizationFilter,因此可以防止进一步执行操作。唯一的不同是,它触发HttpGet到相同的URL而不是默认的400响应,这是一种 Post / Redirect / Get 模式实现。

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

答案 2 :(得分:0)

对d_f代码https://stackoverflow.com/a/56383473/841898的少量修改代替页面重定向,我们仅向ModelState添加错误。然后我们在模型状态摘要中显示。

public class CustomAntiForgeryTokenAttribute : TypeFilterAttribute
{
    public CustomAntiForgeryTokenAttribute() : 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)
        {
            ctx.ModelState.AddModelError("Token", "Validation Token Expired. Please try again");
            ctx.Result = null;

        }
    }
}