我正在.NET Core 2.2 Razor Pages中使用.NET Identity开发一个身份服务器4登录站点(服务器UI),我有一个javascript模式警报,警告用户挂起的空闲超时,然后在达到超时时,它通过设置window.location将用户重定向到注销屏幕。
我遇到的问题是快速入门示例中的 OnGet 显示用户注销提示,因为此时 logoutId 为空。我想在不提示用户的情况下注销。
目前,我已经通过将"autoLogout"参数传递给我的注销页面来解决此问题,该参数绕过了logoutId的检查并设置了ShowLogoutPrompt = false。我知道这在某种程度上违背了检查 logoutId 以确保在没有提示的情况下安全注销的目的。
有没有更好的方法来做我想做的事情?
编辑 16 Jul 2019:似乎处理空闲超时的"正确"方法是设置应用程序 cookie 的令牌到期时间(例如 20 分钟)并启用 SlidingExpire,以便在用户刷新时续订令牌。有关这方面的良好信息,请参阅此博客文章,此github问题线程(包括Brock Allen的评论)以及MS文档中的此信息。
我的麻烦是这个解决方案有两个巨大的缺点。
- SlidingExpiration 仅在用户通过令牌的 TimeSpan>50% 时刷新 cookie(请参阅此处 MS 文档中的 SlidingExpiration 信息)。因此,如果他们将 9m59 刷新为 20 分钟的令牌,他们将在 10 分钟而不是 20 分钟后超时。一种解决方法是将令牌生存期设置为 40 分钟,这将为用户提供至少 20 分钟的空闲时间,但他们最多可能有 40 分钟的空闲时间,这是不可接受的。
- 我的要求之一是警告用户即将超时并为他们提供继续/注销选项的模式。要使用这种 cookie 方法执行此操作,我需要从我的 Javascript(或至少在 C# 中的 Razor 页面)中的 cookie 中读取令牌到期时间,以使我能够确定何时显示警告。即使没有模式要求,我也需要知道令牌何时过期,以便我可能导致页面刷新以将用户发送到登录屏幕。我正在尝试使用以下代码读取到期时间,但在令牌刷新后无法读取正确的到期时间,直到页面第二次刷新,我不知道为什么。
@(DateTime.Parse(((await Context.AuthenticateAsync()).Properties.Items)[".expires"]))
cookie 方法的另一个不太明显的缺点是,如果我设法实现模式弹出窗口并且用户选择继续,那么页面将需要刷新才能获得新令牌,此时任何未保存的数据都将丢失。我想如果他们超时,那么未保存的数据无论如何都会丢失,所以与上述相比,这是一个相对较小的点。
我正在考虑回到我的原始解决方案,它具有所需的功能,但容易被攻击者滥用,攻击者在空闲超时 javascript 中注意到我的 autoLogout 参数,然后可以使用它来提供指向注销页面的热链接。目前,冒这个险感觉是我最好的选择。
我觉得我已经掉进了一个兔子洞,但仍然没有好的解决方案。令我惊讶的是,我想象的常见用例(空闲超时和允许用户继续/注销的警告)在这种身份验证技术中得到了如此糟糕的满足。我错过了什么吗?我的棍子末端有错误吗?
我在这里发布我的最终解决方案。它有效,但我不太喜欢它。有关参考,请详细说明为什么我认为它有点笨拙,以及我认为主要缺点是请参阅上面我原始问题的 7 月 16 日编辑。
在添加身份服务器后的配置服务中,我设置了cookie的滑动过期= true;ExpireTimeSpan = AppSettings.IdleTimeoutMins(请参阅此博客了解如何设置 AppSettings):
// Rename the .AspNetCore.Identity.Application cookie and set up for idle timeout
services.ConfigureApplicationCookie(options =>
{
options.Cookie.Name = "xxxx.Application";
options.SlidingExpiration = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(_config.GetValue<int>("AppSettings:" + nameof(AppSettings.IdleTimeoutMins)));
});
我有一个部分剃刀页面,其中我有 javascript 代码,可以使用倒数计时器向用户显示模式警报。我从AppSettings.IdleTimeoutMins获得超时秒数,并且还有一个设置来确定何时显示警告。有关此位(及其优缺点)的更多详细信息,请参阅我在此处的其他问题和答案:如何在Razor页面中获取 ASP.NET 身份验证票证到期?警告消息为用户提供了"继续"选项,这将刷新页面(以及身份验证票证)或"注销",这会将他们发送到注销确认页面。如果时钟耗尽,则刷新页面,这会导致它们返回到登录屏幕。
在部分的顶部:
@inject RussellLogin.Services.IAppSettings AppSettings;
@using Microsoft.AspNetCore.Authentication;
获取票证上剩余的(假定)秒数:
secondsRemaining = "@(DateTime.Parse(((await AuthenticationHttpContextExtensions
.AuthenticateAsync(Context))
.Properties
.Items)[".expires"])
.Subtract(DateTime.Now)
.TotalSeconds)";
// If secondsRemaining is less than half the expiry timespan then assume it will be re-issued
if (secondsRemaining < timeoutSeconds / 2) {
secondsRemaining = timeoutSeconds;
}