【问题标题】:Best way to refresh accessToken once一次刷新 accessToken 的最佳方法
【发布时间】:2019-01-29 13:11:12
【问题描述】:

从我的 ASP.NET Core 应用程序中,我想使用一个由某种令牌身份验证保护的 API。 由于获取令牌的过程需要很长时间(而且我认为不必要地多次这样做是不好的设计)我想确保如果没有令牌或者它是过期了。

这是我的方法: 我创建了一个新服务并将其注册为单例

   services.AddSingleton<IService, Service>();

服务本身是这样的

public class Service : IService
{
    private object _lock = new object();
    private JwtSecurityToken _accessToken;

    public Service()
    {
        GetNewToken();
    }

    public async Task<object> GetSomething()
    {
        EnsureAccessTokenValidity();
        //Do the api call with the token
    }

    public async Task<object> GetSomethingDifferent()
    {
        EnsureAccessTokenValidity();
        //Do the api call with the token
    }

    private void EnsureAccessTokenValidity()
    {

        if (_accessToken.ValidTo > DateTime.UtcNow) return;
        lock (_lock)
        {
            if (_accessToken.ValidTo > DateTime.UtcNow) return;
            GetNewToken(); 
        }
    }

    private void GetNewToken()
    {
        //Get a new _accessToken 
    }
}

这似乎可行,但我认为应该有一种更优雅的方式来管理它。各位大佬是怎么处理这个问题的?

【问题讨论】:

    标签: c# api .net-core locking jwt


    【解决方案1】:

    您可以为此使用缓存。将其策略的AbsoluteExpiration 设置为ValidTo(最好有一个小的偏移量),一旦过期,它将被自动驱逐。比如:

    private readonly ObjectCache _cache = MemoryCache.Default;
    
    public T GetToken()
    {
        if (!_cache.Contains("token"))
        {
            GetAndCacheNewToken();
        }
    
        return _cache.Get("token") as T;
    }
    
    public void GetAndCacheNewToken()
    {
        T token;
    
        // Get your token.
    
        _cache.Add(
            "token", 
            token, 
            new CacheItemPolicy() {AbsoluteExpiration = token.ValidTo.AddSeconds(-1)});
    }
    

    我将令牌的类型标记为T,因为我不知道它在您的应用中是什么类型。

    【讨论】:

    • 从某种意义上说,我认为这是一个糟糕的解决方案,因为它将缓存引入了等式,这带来了它自己的问题,如缓存失效。在这种情况下,它对管理访问令牌本身的生命周期的单例服务几乎没有任何改进......将令牌生命周期委托给具有绝对过期时间的缓存层也可能导致问题(如果令牌在缓存失效之前过期?)
    • 它没有引入新的生命周期管理服务,而是利用了现有的缓存服务。其次,令牌在缓存使其失效之前不会过期,这就是绝对过期的目的,并且它还受到 1 秒(特定于实现的 tbh)偏移量的保护。
    • 是的,但这假设在缓存过期和令牌过期之间的一秒钟内有一个请求进入。此外,如果多个请求遇到相同的过期缓存项,它们都将并行获取一个新令牌,这取决于发生的次数以及您的应用程序正在运行的实例数量,可以轻松取消不可扩展的身份提供程序。 ..
    • 此外,它在您的应用程序中引入了静态上下文,这扼杀了对利用缓存的服务进行任何可重复测试的所有希望......
    【解决方案2】:

    嘿@askingdumbquestions,欢迎加入社区

    您最初的方法是有意义的,但有一些缺点:

    1. 遇到过期令牌的请求会定期出现性能下降,因为它将在同一进程中获取。
    2. 由于可以并行处理请求 - 可能是多个请求遇到过期令牌并获取新令牌的情况。根据并行运行的请求数量,这很容易使您的身份验证服务速度变慢——这不是我们所希望的!是的:这可以通过一个简单的 Mutex 来解决,围绕 expiration 检查和获取令牌。这将导致许多锁定和任务相互等待,以及必须获取令牌的一个任务! (在获取令牌时,所有请求都将/必须被阻止)。

    但还有另一种方法:您在第一次构造 Service 时获取您的令牌,然后启动一个异步任务,该任务在令牌到期前几分钟获取/刷新令牌!这将确保您始终准备好有效的令牌,并消除对昂贵且容易出错的线程同步的需求,并消除其他副设备必须获取令牌的请求的延迟峰值。

    如果这有帮助或者您需要更详细的解释,请告诉我!

    【讨论】:

      猜你喜欢
      • 2017-11-23
      • 1970-01-01
      • 2012-03-02
      • 2011-02-09
      • 1970-01-01
      • 2017-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多