首页 > 解决方案 > .NET Web API:为不同的用户设置不同的刷新令牌过期时间

问题描述

我正在使用 Identity Server 3 为我的 Angular 客户端进行身份验证和生成访问/刷新令牌。

我目前正在为我的 Angular 客户端设置刷新令牌在 48 小时内过期。

一些使用我的 Angular 应用程序的用户需要连续 100 天登录,而无需重新输入他们的凭据,是否可以仅为特定用户而不是整个客户端设置刷新令牌的到期时间?

我的数据库中有 100 个用户,我希望只有一个特定用户不需要在 100 天内重新进行身份验证,而其余用户应该每 48 小时进行一次身份验证。

类似于以下内容:

if (user == "Super Man") {
    AbsoluteRefreshTokenLifetime = TimeSpan.FromDays(100.0).Seconds,
}

这有可能实现吗?或者我是否仅限于为整个客户端设置刷新令牌过期?

谢谢你

标签: c#.netjwttokenidentityserver3

解决方案


我从未使用过 IdentityServer3,也没有测试下面的代码,但我认为这个概念可能有效。

当我查看 IdentityServer3 的代码时,我可以看到在DefaultRefreshTokenService.CreateRefreshTokenAsync中设置了生命周期:

int lifetime;
if (client.RefreshTokenExpiration == TokenExpiration.Absolute)
{
    Logger.Debug("Setting an absolute lifetime: " + client.AbsoluteRefreshTokenLifetime);
    lifetime = client.AbsoluteRefreshTokenLifetime;
}
else
{
    Logger.Debug("Setting a sliding lifetime: " + client.SlidingRefreshTokenLifetime);
    lifetime = client.SlidingRefreshTokenLifetime;
}

您不想更改核心代码,但您应该能够用自己的实现覆盖 IRefreshTokenService。

当我以CustomUserService 示例中的代码为例时:

internal class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.Map("/core", coreApp =>
        {
            var factory = new IdentityServerServiceFactory()
                .UseInMemoryClients(Clients.Get())
                .UseInMemoryScopes(Scopes.Get());

            var refreshTokenService = new MyDefaultRefreshTokenService();

            // note: for the sample this registration is a singletone (not what you want in production probably)
            factory.RefreshTokenService = new Registration<IrefreshTokenService>(resolver => refreshTokenService);

其中 MyDefaultRefreshTokenService 是 DefaultRefreshTokenService 的副本。

为了使其编译,添加 IdentityModel (v1.13.1) 的 NuGet 包并添加以下类:

using System;

namespace IdentityServer3.Core.Extensions
{
    internal static class DateTimeOffsetHelper
    {
        internal static Func<DateTimeOffset> UtcNowFunc = () => DateTimeOffset.UtcNow;

        internal static DateTimeOffset UtcNow
        {
            get
            {
                return UtcNowFunc();
            }
        }

        internal static int GetLifetimeInSeconds(this DateTimeOffset creationTime)
        {
            return (int)(UtcNow - creationTime).TotalSeconds;
        }
    }
}

现在有一些关于事件的编译错误。您可以删除事件以测试代码。如果它有效,您可以随时选择添加它们。

现在为每个用户执行 RefreshTokenLifetime。在您的 RefreshTokenService 版本中,您可以删除客户端代码并使用您自己的逻辑来确定每个用户的生命周期。

该主题可用,但我不知道它是否已经包含足够的信息。但如果是这样,那么您可以访问 userManager 以从存储中读取生命周期。或者使用替代方法来传递生命周期信息(也许您可以使用包含生命周期值的声明)。

同样,我没有对此进行测试,但我认为这个概念应该有效。


推荐阅读