javascript - 停止刷新 token 的竞争条件?

标签 javascript c# reactjs authentication jwt

我有一个 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/

相关文章:

C# WebBrowser控件: window.外部访问子对象

c# - Powershell 如何知道在哪里可以找到要导入的模块?

c# - 如何将 CollectionViewSource 传递给转换器?

javascript - 为什么我们在 redux 中使用展开运算符

javascript - 如何在 React 上正确地将 onclick 处理程序绑定(bind)到 `this`

JavaScript 反向 DNS 查找

javascript - Node.js 中的未知编码错误

c# - 如何在 watin 中获取文本框的类型?

javascript - 如何使用 ReactJS 以两种方式使表中的列可排序

javascript - Formik 在空白字段上也显示错误