【发布时间】:2022-11-07 14:42:20
【问题描述】:
它是一个 web api,它在服务器端使用访问令牌访问某些资源。令牌在 180 秒后过期。请求最初会从令牌端点生成令牌并将其存储在 Redis 缓存中,该操作之后是使用该令牌的后续调用。检查令牌过期,当请求发现它过期时,它将获得一个新的访问令牌并在缓存中更新它。
问题是,如果两个请求发现令牌已过期,就说第一个请求获得了一个新令牌 - abc123 并更新它,但对于第二个请求,它已经检查过令牌是否已过期,现在这将还获得一个新令牌 - xyz321 并将 abc123 替换为 xyz321。但是对于第一个请求,令牌abc123 不再有效,因此后续调用将失败,令牌abc123。
所以这是我试图防止这个问题的东西:
public async Task<string> GetAccessTokenAsync()
{
string token = string.Empty;
using (Mutex mutex = new Mutex(false))
{
try
{
if (_storage.IsTokenExpired()) // returns "false" if expired or no token set
{
mutex.WaitOne();
if (_storage.IsTokenExpired())
{
token = await AccessTokenEndpointCallAsync();
_storage.StoreAccessToken(token);
}
else
{
token = _storage.ReadAccessToken();
}
}
else
{
token = _storage.ReadAccessToken();
}
}
catch(Exception)
{
throw;
}
finally
{
mutex.ReleaseMutex();
}
}
return token;
}
好吧,如果我启动浏览器并调用 api,一切正常,但如果我打开另一个浏览器并进行调用,则会引发错误 -
消息:对象同步方法是从 不同步的代码块。堆栈跟踪:在 System.Threading.Mutex.ReleaseMutex()
【问题讨论】:
-
使用静态
SemaphoreSlim,它允许您锁定异步方法,
标签: c# asp.net-core redis asp.net-core-webapi