C# AntiForgeryToken过期空白页

C# AntiForgeryToken过期空白页,c#,asp.net-core,identityserver4,antiforgerytoken,C#,Asp.net Core,Identityserver4,Antiforgerytoken,我将IdentityServer4与ASP.NET Core 2.2一起使用。在登录后方法中,我应用了ValidateAntiForgeryToken。通常,在登录页面上坐上20分钟到2小时后,然后尝试登录会生成一个空白页面 如果你看邮递员控制台,你会得到一个400错误的请求消息。然后,我在Antifforgery选项中将Cookie过期时间设置为90天。我能够让页面坐在长达6个小时,仍然登录。然而,在大约8小时(过夜)之后,我在尝试登录之后再次收到空白页。 [HttpPost] [Valida

我将IdentityServer4与ASP.NET Core 2.2一起使用。在登录后方法中,我应用了ValidateAntiForgeryToken。通常,在登录页面上坐上20分钟到2小时后,然后尝试登录会生成一个空白页面

如果你看邮递员控制台,你会得到一个400错误的请求消息。然后,我在Antifforgery选项中将Cookie过期时间设置为90天。我能够让页面坐在长达6个小时,仍然登录。然而,在大约8小时(过夜)之后,我在尝试登录之后再次收到空白页。
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login

我希望能够坐在登录页面上90天,这是cookie的持续时间,但这不起作用。我如何让AntiforgeryToken的cookie持续整个90天或我设置的任何时间,而不是超时或过期?是否有办法捕获此错误并将用户重定向回登录方法?

这是我的最终解决方案。我使用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))]
2021年更新 自ASP.Net Core 3.0 MS以来,使
ValidateAntiforgeryTokenAuthorizationFilter
内部。现在我们必须复制粘贴,才能导出。但很可能我们不需要这样做。要更改结果行为,我们只需测试
IAntiforgeryValidationFailedResult的上下文,并按照下面的说明进行操作

使用Microsoft.AspNetCore.Mvc;
使用Microsoft.AspNetCore.Mvc.Core.Infrastructure;
使用Microsoft.AspNetCore.Mvc.Filters;
命名空间BasicWebSite.Filters
{
公共类重定向AntiforgeryValidationFailedResultFilter:IAlwaysRunResultFilter
{
ResultExecuting上的公共void(ResultExecutingContext)
{
if(context.Result为IAntiforgeryValidationFailedResult结果)
{
上下文。结果=
新的重定向结果(“http://example.com/antiforgery-redirect");
}
}
ResultExecuted上的公共无效(ResultExecutedContext)
{ }
}
}
然后在控制器内:

//POST:/Antiforgery/LoginWithRedirectResultFilter
[HttpPost]
[异名]
[ValidateAntiForgeryToken]
[TypeFilter(typeof(重定向AntiforgeryValidationFailedResultFilter))]
公共字符串LoginWithRedirectResultFilter(LoginViewModel模型)
{
返回“Ok”;
}
原始答案涵盖.NETCore2.2 还有一个使用默认实现的实现,包括所有预检查、日志记录等,它仍然是一个
授权过滤器
,因此阻止任何进一步的操作执行。唯一的区别是它触发同一url的
HttpGet
,而不是默认的400响应,这是一种Post/Redirect/Get模式实现

public类AnotherAntiForgeryTokenAttribute:TypeFilterAttribute
{
public AnotherAntiForgeryTokenAttribute():base(typeof(AnotherAntiforgeryFilter))
{
}
}
公共类AnotherAntiforgeryFilter:ValidateAntiforgeryTokenAuthorizationFilter,
IAsyncuAuthorization过滤器
{
公共AnotherAntiforgeryFilter(IAntiforgery a,l):基础(a,l)
{
}
异步任务IAsyncAuthorizationFilter.OnAuthorizationAsync(
授权筛选器上下文(ctx)
{
等待base.OnAuthorizationAsync(ctx);
如果(ctx.Result为IAntiforgeryValidationFailedResult)
{
//接下来的四行是可选的,只是说明了一种方法
//保存一些敏感数据,如初始查询
//表格必须支持这一点
var request=ctx.HttpContext.request;
var url=request.Path.ToUriComponent();
if(request.Form?[“ReturnUrl”]。计数>0)
url=$“{url}?ReturnUrl={Uri.EscapeDataString(request.Form?[“ReturnUrl”])}”;
//下面是唯一真正的定制
ctx.Result=新的LocalRedirectResult(url);
}
}
}

对d\U f代码进行轻微修改,而不是页面重定向,我们只是将错误添加到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;

        }
    }
}

里面不仅有cookie,还有一个令牌。MS有一个打开的设置,它是ttl。但据我所知,默认情况下,只要浏览器保持会话,该会话就应该有效。。。但您可以使用其打开的代码进行检查:)以及关于更改行为:您可以覆盖筛选器并重定向到具有相同名称的操作,但使用HttpGet而不是返回400状态。在验证失败后,我可以使用以下命令控制结果:
等待此命令。_antiforgery.IsRequestValidAsync(HttpContext)。现在,这对我来说非常有用,而不是使用内置属性。很高兴它对您有效,但一般来说,最好在任何地方都使用一些通用方法,您可以通过将实现包装到新属性中来完成任务,然后在下面描述它,作为寻找类似解决方案的其他人的答案…为什么需要
AntiForgeryToken
?你在这里破坏了AntiForgeryToken的目的,你最好一开始就没有一个,而不是有这么长的时间使用该token。我给了你我的投票,并添加了一个替代方案。可能会简单一点,但总的来说这并不重要。我将对此进行测试,稍后再与您联系。我们决定在验证失败时不使用ReturnUrl,因为它可能存在风险。我现在带着一条信息回到一个视图。这很有效。我将使用您的解决方案,因为它使用默认的AntiForgery验证。感谢您的帮助。请确定ValidateAntiforgeryTokenAuthorizationFilter的命名空间。我正在使用asp.NETCore5,但它似乎找不到该类。所需的“使用”语句是什么?情况发生了变化。更新了答案。感谢您的更新。但是现在,怎么办
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;

        }
    }
}