.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");
}
当我创建一个新的 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");
}