我正在使用.NET Core 2.2 Razor页面中的.NET Identity在Identityserver4登录站点(服务器UI)上工作,我有一个javascript模态警报,警告用户未决的空闲超时,然后在达到超时时重定向通过设置window.location
进入注销屏幕我遇到的麻烦是,快速入门示例中的OnGet显示了一个用户退出提示,因为此时logoutId为null。我想注销而不提示用户。
目前,我通过向“注销”页面传递“ autoLogout”参数来解决此问题,该参数绕过了logoutId的检查并设置了ShowLogoutPrompt = false。我知道这有点违背了检查logoutId以确保在没有提示的情况下安全注销的目的。
是否有更好的方法来做我想做的事情?
编辑2019年7月16日: 似乎处理空闲超时的“正确”方法是设置应用程序cookie的令牌到期(例如20分钟)并启用SlidingExpiration,以便在用户刷新时更新令牌。有关此的详细信息,请参阅MS文档中的this blog post,this github issue thread (including comments from Brock Allen)和this info。
我的麻烦是此解决方案有两个巨大的缺点。
@(DateTime.Parse(((await Context.AuthenticateAsync()).Properties.Items)[".expires"]))
Cookie方法的另一个不太重要的缺点是,如果我设法实现模式弹出窗口,并且用户选择继续,则页面将需要刷新以获取新令牌,这时所有未保存的数据都将丢失。我想如果它们超时了,尽管如此,未保存的数据仍然会丢失,因此与上述相比,这是一个相对较小的问题。
我正在考虑回到具有所需功能的原始解决方案,但攻击者可能会滥用它,因为攻击者在空闲超时javascript中注意到了我的autoLogout参数,然后可以使用它来提供注销的热链接页。目前,冒险是我最好的选择。
我觉得我在这上面掉了一个兔子洞,但仍然没有好的解决方案。令我惊讶的是,我想这是一种常见的用例(空闲超时,并带有警告消息,允许用户继续/注销),但是使用这种身份验证技术的情况却是如此。我想念什么吗?我的杆子末端错了吗?
答案 0 :(得分:0)
经过深思熟虑,我得出的结论是前线无法启动注销。它违反了永远不信任客户的原则。换句话说,可以说,如果用户设法禁用javascript,则它可以永远保持登录状态。
因此,您应该从IdentityServer内部触发注销。为此,您可以创建一个本地服务,其行为类似于已经存在的TokenCleanup service。
该服务可以跟踪用户并触发注销。某种“内部反向通道”注销。具有相同的经验:用户尝试与服务器联系后,就会发现自己已注销,因为前端不知道注销。
您可以通过以下两种方法解决此问题:添加代码以向前端发出信号以刷新页面或保留您已有的代码,但仅在会话到期后刷新页面。
答案 1 :(得分:0)
我在这里发布我的最终解决方案。它有效,但我不太喜欢。作为参考,详细说明了为什么我认为它有点笨拙,以及我认为主要缺点是在7月16日对上述原始问题的编辑。
在添加Identityserver之后,在ConfigureServices中,我设置了Cookie的SlidingExpiration = true; ExpireTimeSpan = AppSettings.IdleTimeoutMins(有关如何设置AppSettings,请参见this post)
// 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获得timeoutSeconds,并且还有一个设置来确定何时显示警告。有关此位(及其优点和缺点)的更多详细信息,请参见此处的其他问题和解答:this blog警告消息为用户提供了“继续”选项,该选项可刷新页面(并因此刷新身份验证凭单)或“注销”,将其发送到“注销确认”页面。如果时钟用尽,则会刷新页面,这将使它们返回“登录”屏幕。
在Partial顶部:
@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;
}