发布于 2026-01-06 0 阅读
0

使用 JWT 和刷新令牌的 API 身份验证工作流程

使用 JWT 和刷新令牌的 API 身份验证工作流程

大家好,这是我的第一篇帖子,请多多包涵 :P

所以,我希望这篇文章能帮助到所有想要构建身份验证系统的人。我分享的是工作流程,而不是具体的实现方式,这样你可以根据自己的需求进行调整。

我会在文章中穿插一些场景示例,然后逐步讲解服务器端,最后是客户端。我假设你已经有一个注册系统。

情景第一部分

用户已注册。好的,接下来我们需要发送一个 JWT 和一个刷新令牌。服务器会创建它们并发送给用户,用户的浏览器会保存这些令牌,然后我们可爱的小用户就可以在我们的应用中自由探索了。那么,实际发生了什么呢?

服务器端

  • 客户已注册
  • 为指定用户创建了短期 JWT 和刷新令牌
  • 将刷新令牌保存在数据库中,可以是像 Redis 这样的键值数据库。
  • 将 JWT 发送回客户端,并将刷新令牌添加到客户端的 Cookie 存储中,并启用 HttpOnly 和 Secure 标志。

您可以在 Node.js 中这样设置 cookie:

response.setHeader('Set-Cookie', 'foo=bar; HttpOnly');
Enter fullscreen mode Exit fullscreen mode

客户端

  • 访问服务器注册端点。
  • 将 JWT 保存到本地存储。

友情提示:本地存储容易受到跨站脚本攻击 (XSS),请小心 :)

好吧,虽然内容不多。但我们的这份小说明可能会引发一些问题。最具体的问题在于:既然 JWT 存在安全漏洞,为什么我们要将其保存到 localStorage 中呢?

答案

我们将 JWT 保存到客户端本地存储中,因为您可能已经注意到,我们的 JWT 有效期很短,大约只有 30 分钟。这样我们就可以把 JWT 添加到 API 请求的 Authorization 标头中(也就是 bearer 部分)。

然后我们创建了另一个名为刷新令牌的令牌,它可以是任何东西,比如你宠物名字的倒序加上一个计数器,或者一些随机数……什么都可以!我个人比较喜欢用一个叫做“uuid”的Node包。我们将刷新令牌保存到客户端的cookie存储中,并设置了httponly和secure标志。这意味着这个cookie无法被JavaScript访问。而secure标志是关于https的,你应该明白它的作用 :P

这样,当用户访问我们的 API 时,我们的服务器就可以验证用户的 JWT 和刷新令牌。

场景第二部分

用户在我们的应用中永远不会感到无聊!他会不断刷新页面,期待新鲜内容,但猜猜看,我们的小用户发生了什么?30分钟已经过去了!所以您的JWT已过期。现在怎么办?

这次我将用序列图的方式来解释。

客户端

  • 用户使用已过期的 JWT 发起 API 请求。

服务器端

  • 收到 API 请求,检查 JWT 和刷新令牌。糟糕, JWT 已过期,向客户端发送未授权响应 (401)。

客户端

  • 收到来自先前 API 请求的未经授权的响应。
  • 点击 API 的刷新端点。

服务器端

  • 已收到过期的 JWT,已检查并确认刷新令牌已分配给当前用户。现在刷新 JWT 并将其发送回用户。

客户端

  • 已收到 JWT,已将其再次保存到本地存储中。
  • 重新执行失败的 API 请求。
  • 继续运营。

在 Node.js 的 jsonwebtoken 包中,验证 JWT 时有一个选项:ignoreExpiration。您可以用它来检查令牌是否被修改过。

情景第三部分

我们的用户困了,想登出。但他不是无聊,只是想睡觉而已 :)。他点击了登出按钮。接下来会发生什么?

客户端

  • 清除本地存储或直接删除 JWT。
  • 发起 API 注销请求。

服务器端

  • 收到登出请求。从数据库(类似 Redis 那样 :P)中删除刷新令牌。
  • 将刷新令牌 cookie 的过期日期设置为过去的任意日期。

用户已登出。

第一次发这么长的帖子啊?如果帖子可以编辑的话,我可能会添加更多信息 :P。

重要提示:移动端认证方式与此不同。我会在以后的文章中详细介绍。

我们下篇文章再见!

文章来源:https://dev.to/gokayokyay/api-authentication-workflow-with-jwt-and-refresh-tokens-5312