我有一个 reactjs 站点和 asp.net 核心后端,但我遇到了刷新 token 的问题。
当有人登录我的网站时,他们会得到一个访问 token 和刷新 token (非常标准)。现在我设置了一个比访问 token 的时间更短的计时器。
当他们打开多个标签时,这一切都很好。问题是他们都共享本地存储(需要自动登录所以不能使用 session 存储)
场景
2 个标签页依次打开。在访问 token 失效前 2 分钟设置了 2 个计时器。
第一次触发首先将刷新 token 发送到服务器并带回新的刷新/访问 token 。在服务器上删除发送的刷新 token 。
第二个计时器在第一个计时器之后不久触发(第一个计时器正在工作),但现在很可能刷新 token 已被删除,从而使此请求无效。
如何停止这种竞争条件?
var foundRefreshToken = dbContext.Tokens.FirstOrDefault(x => x.Value == refreshToken);
if (foundRefreshToken == null)
{
return null;
}
var newRefreshToken = CreateRefreshToken(foundRefreshToken.ClientId, foundEmployee.Id);
dbContext.Tokens.Remove(foundRefreshToken);
dbContext.Tokens.Add(newRefreshToken);
dbContext.SaveChanges();
private Token CreateRefreshToken(string clientId, string userId)
{
return new Token()
{
ClientId = clientId,
EmployeeId = userId,
Value = GenerateRefreshToken(),
CreatedDate = DateTime.UtcNow
};
}
// high level js
refreshTimer;
setRefreshTimer(intervals) {
this.clearRefreshTimer();
this.refreshTimer = setInterval(() => {
this.refreshAuthentication();
}, intervals);
}
我能想到的唯一两件事是不要删除刷新 token (但这会导致自动登录出现问题)
或者我在本地存储中有一个标志“锁定”第一个选项卡以进行刷新,而其他选项卡则等待查看它是否执行(猜测需要另一个计时器)。如果没有,则下一个尝试。
还有其他人有其他想法吗?
最佳答案
最佳实践要求刷新 token 只能使用一次,并在每次使用时发出一个新 token 。再次使用旧 token 的尝试应被视为 token 被盗 - 该用户的所有未完成 token 都应失效,并且任何新的访问尝试都应要求完全登录。
当两个 session 共享一个公共(public)刷新 token 时(例如,当两个选项卡在浏览器中打开并且 token 存储在仅限 http 的 cookie 中时),就会出现竞争条件。当出现两个 session 使用相同的刷新 token 同时尝试刷新的情况时,第一个到服务器的 session 获得一个有效的新 token ,但第二个 session 发现他们的 token 现在无效并被注销。
正如 OP 所提到的,这可以在前端通过使用忙标志之类的机制来解决,这样第一次刷新必须在第二次刷新之前完成。
在后端,您可以拥有一种机制,允许刷新 token 在完全失效或删除之前在很短的时间内(仅几秒钟)重复使用。
关于javascript - 停止刷新 token 的竞争条件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56082559/