C# 刷新accessToken一次的最佳方法
从我的ASP.NET核心应用程序中,我想使用一个由某种令牌身份验证保护的API。 由于获取令牌的过程需要相当长的时间(我认为不必要地多次这样做是糟糕的设计),因此我希望确保在没有令牌或令牌过期的情况下,仅执行一次获取令牌的API调用 这是我的方法: 我创建了一个新服务,并将其注册为singletonC# 刷新accessToken一次的最佳方法,c#,api,.net-core,locking,jwt,C#,Api,.net Core,Locking,Jwt,从我的ASP.NET核心应用程序中,我想使用一个由某种令牌身份验证保护的API。 由于获取令牌的过程需要相当长的时间(我认为不必要地多次这样做是糟糕的设计),因此我希望确保在没有令牌或令牌过期的情况下,仅执行一次获取令牌的API调用 这是我的方法: 我创建了一个新服务,并将其注册为singleton services.AddSingleton<IService, Service>(); services.AddSingleton(); 服务本身是这样的 public cla
services.AddSingleton<IService, Service>();
services.AddSingleton();
服务本身是这样的
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
}
}
公共类服务:iSeries
{
私有对象_lock=新对象();
私有JwtSecurityToken\u accessToken;
公共服务()
{
GetNewToken();
}
公共异步任务GetSomething()
{
确保reaccesstokenvalidity();
//使用令牌执行api调用
}
公共异步任务GetSomethingDifferent()
{
确保reaccesstokenvalidity();
//使用令牌执行api调用
}
私有void EnsureAccessTokenValidity()
{
if(_accessToken.ValidTo>DateTime.UtcNow)返回;
锁
{
if(_accessToken.ValidTo>DateTime.UtcNow)返回;
GetNewToken();
}
}
私有void GetNewToken()
{
//获取新的\u accessToken
}
}
这似乎是可行的,但我认为应该有一个更优雅的方法来处理这个问题。你们是如何处理这个问题的?你们可以使用缓存来解决这个问题。将其策略的
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
,因为我不知道它在你的应用程序中是什么类型。hey@askingdumbquestions,欢迎加入社区
您最初的方法是合理的,但有一些缺点:
服务时获取令牌,然后启动异步任务,在令牌过期前几分钟获取/刷新令牌!这将确保您始终准备好一个有效的令牌,并且不再需要昂贵且容易出错的线程同步,并且消除了其他设备必须获取令牌的那些请求的延迟峰值
让我知道这是否有用,或者您需要更详细的解释在这个意义上,我认为这是一个糟糕的解决方案,它将缓存引入到等式中,缓存中有自己的问题,比如缓存失效。在这种情况下,它也提供了几乎没有改善,有一个单一的服务,管理生命周期的访问令牌本身。。。将令牌生存期委托给具有绝对过期的缓存层也会导致问题(如果令牌在缓存使其失效之前过期怎么办?),它不会引入用于管理生存期的新服务,而是利用现有的单缓存。其次,令牌不会在缓存使其失效之前过期,这就是绝对过期的目的,它还受到1秒(特定于实现的tbh)偏移量的保护。是的,但这假设在缓存过期和令牌过期之间的一秒钟内有一个请求进入。如果多个请求遇到相同的过期缓存项,它们都将并行获取一个新令牌,这取决于发生的次数和应用程序正在运行的实例数量,可以轻松关闭不太可扩展的身份提供程序……此外,它将静态上下文引入到应用程序中,从而扼杀了对利用该令牌的服务进行任何可重复测试的希望缓存。。。