如何在Razor Page中获取ASP.NET Identity身份验证票证到期?

时间:2019-07-18 16:25:38

标签: asp.net-identity asp.net-core-2.0 identityserver4 razor-pages

我正在将Identityserver4与ASP.NET Identity一起使用,并将cookie配置为SlidingExpiration = true和ExpireTimeSpan = 20分钟。我想在用户即将超时时向用户提供警告,因此尝试访问Cookie中的“ .expiry”值。

到目前为止,我已经能够使用下面的Razor代码读取 到期时间。 但是,这在用户刷新票证时无法读取正确的到期时间。根据{{​​3}},如果滑动用户在获得票证后10分钟或更长时间(> = ExpireTimeSpan的50%)刷新页面,则应该为我的用户提供一张新票证。这样做很好,但是这样做的话,下面的代码提供了旧的到期时间,直到用户第二次刷新页面为止!

@(DateTime.Parse(((await Context.AuthenticateAsync()).Properties.Items)[".expires"]))

我想知道的是,如何在提供新票证时生成的页面上获得正确的到期时间?

2 个答案:

答案 0 :(得分:1)

这里的问题是在呈现页面后进行续订-新属性仅在后续请求中可用。

一个选项可能是使用客户端代码轮询最近的到期时间,但这会成为保持活动状态,这可能不是您想要的。

为缓解上述问题,您可以创建自己的cookie中间件实现(所有源代码都在github上)并自定义滑动到期逻辑(CheckForRefresh和RequestRefresh)。您还可以将新的到期时间添加到HttpContext中,从而使它更早可用于您的控制器代码。

源代码:https://github.com/aspnet/Security/tree/master/src/Microsoft.AspNetCore.Authentication.Cookies

您只需要创建自己的CookieAuthenticationHandler版本(少于500行代码)和您自己的注册助手(请查看CookieExtensions):

public static AuthenticationBuilder AddCustomCookie(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<CookieAuthenticationOptions> configureOptions)
{
    builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<CookieAuthenticationOptions>, PostConfigureCookieAuthenticationOptions>());
    return builder.AddScheme<CookieAuthenticationOptions, CustomCookieAuthenticationHandler>(authenticationScheme, displayName, configureOptions);
}

答案 1 :(得分:0)

我已经解决了我的问题,我不太喜欢这个解决方案,因为它很hacky 。它确实可以工作,所以我将其发布在这里以防万一。如果有人可以帮助我理解更好的解决方案,我将不胜感激,如果有的话,我会编辑此答案或删除它,以取而代之。

我以与问题基本相同的方式获得身份验证凭单的有效期,然后如果剩余的ExpireTimeSpan设置少于50%,我认为它会续订(可能有点冒险,但到目前为止,这是我最好的)已经管理好了)。我用它来计算到超时之前剩余的假定秒数,然后在决定何时向用户显示警告时使用此值。

在剃刀顶部(部分):

@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;
}