C# ASP.NET Core 6 Web API、线程安全、用于重用访问令牌的单一实例实现

C# ASP.NET Core 6 Web API, Thread Safe, singleton implementation to reuse access tokens

提问人:Melu 提问时间:11/4/2023 最后编辑:Melu 更新时间:11/7/2023 访问量:108

问:

我的 ASP.NET Core 6 Web API A 正在调用另一个返回访问令牌的 API B,我想使用相同的令牌(直到它过期)随后调用 B 上的多个操作。我创建了一个令牌类,它将保存令牌的实际值和过期时间

public sealed class Token
{
    private static readonly Lazy<Token> lazy =
   new Lazy<Token>(() => new Token());

    public static Token Instance { get { return lazy.Value; } }
   
    public Token()
    {
    } 
 
    public string TokenValue { get; set; }
    public DateTime ExpiresOn { get; set; }

    public bool HasTokenExpired()
    { 
      if (string.IsNullOrEmpty(TokenValue))
      {
        return true;
      }

      if (DateTime.UtcNow >= ExpiresOn.AddSeconds(-20))
      {
        return true;
       }
        return false;           
    }
}

然后我有另一个类,它有两个操作:

Public class TokenResource : ITokenResource
{
    private static Token Token
    {
      get
      {
         return Token.Instance;
      }
     }

    public async Task<string> GetTokenAsync()
    {
        if (Token.HasTokenExpired())
        {
            await RefreshTokenAsync();
        }            
        return Token.TokenValue;                
    }  

    public async Task RefreshTokenAsync()
    {
         // does a http post and gets the token
         var tokenString = JObject.Parse(tokenResponseAsString)["access_token"].Value<string>();            
         Token.TokenValue = tokenString;
         Token.ExpiresOn = SetTokenExpirationDate(tokenString);            
    }
}

在启动时,我将类设置为单例:TokenResource

 builder.Services.AddSingleton<ITokenResource, TokenResource>();

所有这些似乎都运行良好,但我想知道这是否是实现线程安全单例的正确方法,或者这是否是矫枉过正,我们不需要锁定对象,因为它已经是单例。

- 更新 - 删除和添加ReaderWriterLockSlimLazy<T>

C# 线程安全 ASP.NET-CORE-WEBAPI 单例 net-6.0

评论

1赞 Denis Micheal 11/4/2023
添加为服务可确保在应用程序中构建一次服务并在所有 http 请求之间共享,这并不意味着它会阻止多个线程同时调用 或 .ITokenResourceSingletonRefreshTokenAsync()HasTokenExpired()
1赞 Fildor 11/4/2023
^ 这就是为什么我建议使用 with a factory 方法。然后,您可以摆脱所有锁定。Lazy<T>
1赞 Fildor 11/5/2023
出于好奇,我决定创作一个关于我上面评论的意思的小小提琴: dotnetfiddle.net/IFqWOj 如果你喜欢它,我可以详细说明成一个答案。
0赞 Melu 11/7/2023
谢谢@fildro - 我不是很熟悉,但更新了我的代码以反映实现,我确实参考了他们 Q 使用互锁的另一篇帖子Interlocked.CompareExchangeLazy<T>

答: 暂无答案