.Net Core 在 cookie 过期后无法 post 退出页面

.Net Core cannot post to Logout page after cookie expiration

当我创建一个新的 Asp.Net 核心 Web 应用程序和

    services.ConfigureApplicationCookie(options =>
    {
        options.ExpireTimeSpan = TimeSpan.FromSeconds(5);
    });

然后我在 5 秒后退出。但是,当时我的页面上仍然有注销按钮,如果我点击该按钮,我会得到 400 Bad Request 返回。

然后我尝试删除过期代码,通过注销按钮注销,然后使用 Postman post 进行注销 post 操作,但我得到了相同的结果。

    [AllowAnonymous]
    public class LogoutModel : PageModel
    {
        private readonly SignInManager<IdentityUser> _signInManager;
        private readonly ILogger<LogoutModel> _logger;

        public LogoutModel(SignInManager<IdentityUser> signInManager, ILogger<LogoutModel> logger)
        {
            _signInManager = signInManager;
            _logger = logger;
        }

        public void OnGet()
        {
        }

        //When I am logged out (whether by clicking on the logout button or after cookie expiration), 
        //and try to invoke this action, I get a 400 Bad Request back
        public async Task<IActionResult> OnPost(string returnUrl = null)
        {
            await _signInManager.SignOutAsync();
            _logger.LogInformation("User logged out.");
            if (returnUrl != null)
            {
                return LocalRedirect(returnUrl);
            }
            else
            {
                return Page();
            }
        }
    }

有人知道这里发生了什么吗?

编辑:顺便说一句,我正在使用 .Net Core 2.2

所有 post 均受开箱即用的防伪令牌保护。当用户登录时,防伪令牌实际上与该特定用户相关联。由于用户的身份验证很快就会过期,几乎在页面加载时,令牌就已经无效了。它是为特定用户创建的,但该用户不再经过身份验证。因此,令牌验证将在 post 注销请求时失败,您会收到 400。

一个快速修复方法是将 [IgnoreAntiforgeryToken] 属性应用到您的 LogoutModel。这在技术上移除了一层安全性,但我看不出恶意的不良行为者伪造对注销端点的请求可以获得多少。

然而,这主要是一个人为的问题。您可能会调低 auth cookie 过期时间以测试过期时会发生什么,但 5 秒不是一个实际的过期时间。这样一来,用户实际上必须对每个请求重新进行身份验证,这意味着他们永远无法真正通过登录页面。一旦他们登录,他们就会过期,并且必须重新登录。对于更实际的数字,如 20 分钟,用户在同一页面上停留 20 分钟以上,然后尝试单击 "Logout" 的可能性相当低,因此这基本上不是问题。

在布局页面上检查会话过期并在帐户控制器中调用注销操作

在 Layout.cshtml 部分的脚本下方并在 Appsettings.json

中添加会话超时
<script>
    //session end
    var sessionTimeoutWarning = @Configuration.GetSection("Cookie")["sessionTimeout"] - 1;

    var sTimeout = parseInt(sessionTimeoutWarning) * 60 * 1000;
    setTimeout('SessionEnd()', sTimeout);

    function SessionEnd() {
        window.location = "/Account/LogOff";
    }
    </script>

在帐户控制器中添加注销操作

 public ActionResult LogOff()
        {
            _signInManager.SignOutAsync();
            return RedirectToAction("Index", "Home");
        }