一次刷新 accessToken 的最佳方法
Posted
技术标签:
【中文标题】一次刷新 accessToken 的最佳方法【英文标题】:Best way to refresh accessToken once 【发布时间】: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
这似乎可行,但我认为应该有一种更优雅的方式来管理它。各位大佬是怎么处理这个问题的?
【问题讨论】:
【参考方案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,欢迎加入社区
您最初的方法是有意义的,但有一些缺点:
-
遇到过期令牌的请求会定期出现性能下降,因为它将在同一进程中获取。
由于可以并行处理请求 - 可能是多个请求遇到过期令牌并获取新令牌的情况。根据并行运行的请求数量,这很容易使您的身份验证服务速度变慢——这不是我们所希望的!是的:这可以通过一个简单的 Mutex 来解决,围绕 expiration 检查和获取令牌。这将导致许多锁定和任务相互等待,以及必须获取令牌的一个任务! (在获取令牌时,所有请求都将/必须被阻止)。
但还有另一种方法:您在第一次构造 Service
时获取您的令牌,然后启动一个异步任务,该任务在令牌到期前几分钟获取/刷新令牌!这将确保您始终准备好有效的令牌,并消除对昂贵且容易出错的线程同步的需求,并消除其他副设备必须获取令牌的请求的延迟峰值。
如果这有帮助或者您需要更详细的解释,请告诉我!
【讨论】:
以上是关于一次刷新 accessToken 的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章