C# 刷新accessToken一次的最佳方法

C# 刷新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

从我的ASP.NET核心应用程序中,我想使用一个由某种令牌身份验证保护的API。 由于获取令牌的过程需要相当长的时间(我认为不必要地多次这样做是糟糕的设计),因此我希望确保在没有令牌或令牌过期的情况下,仅执行一次获取令牌的API调用

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

   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,欢迎加入社区

您最初的方法是合理的,但有一些缺点:

  • 遇到过期令牌的请求通常会受到性能影响,因为它将在同一进程中获取
  • 由于请求可以并行处理,因此可能会有多个请求遇到过期的令牌并获取一个新令牌。根据并行运行的请求量,这可能会很容易地降低身份验证服务的速度—这不是我们想要的!是:这可以通过围绕支出检查和获取令牌的简单互斥来解决。这将导致大量的锁定和任务等待对方以及必须获取令牌的一个任务!(提取to令牌时,所有请求将/必须被阻止)
  • 但是还有另一种方法:您在第一次构建
    服务时获取令牌,然后启动异步任务,在令牌过期前几分钟获取/刷新令牌!这将确保您始终准备好一个有效的令牌,并且不再需要昂贵且容易出错的线程同步,并且消除了其他设备必须获取令牌的那些请求的延迟峰值


    让我知道这是否有用,或者您需要更详细的解释