章
目
录
今天就给大家详细拆解一下双Token无感刷新的全流程,还会附上专业的时序图和流程图,帮助大家轻松理解,一文搞懂双Token无感刷新实现原理。
一、双Token无感刷新概念
在双Token无感刷新方案里,有两个非常关键的概念,分别是Access Token(访问令牌)和Refresh Token(刷新令牌)。
(一)Access Token(访问令牌)
它的有效期比较短,一般在15分钟到1小时之间。主要用途是访问那些受保护的API资源。每次我们向API发起请求的时候,都要在请求头里带上它,格式通常是Authorization: Bearer <token>
。因为它的有效期短,就算不小心泄露了,风险也相对没那么大,毕竟很快就会过期失效。
(二)Refresh Token(刷新令牌)
和Access Token不同,Refresh Token的寿命要长得多,可能是7天、30天,甚至更久。它只有一个作用,就是用来获取新的Access Token。千万要记住,不能在访问普通API的时候携带它,只有当Access Token过期了,我们调用专门的刷新接口时才会用到它。在前端存储Refresh Token的时候,要选择更安全的方式,比如存在localStorage
、sessionStorage
里,或者使用更安全的HttpOnly
Cookie来存储。
二、双Token无感刷新详细流程
双Token无感刷新的流程可以细分为登录流程、访问受保护的API、Token刷新流程以及异常处理流程这几个部分。
(一)登录流程
- 用户操作:用户在前端输入账号和密码,点击登录。
- 前端处理:前端把用户输入的凭据发送到后端的登录接口,一般是
/login
。 - 后端处理:后端接收到请求后,会验证用户的凭据。如果验证成功,就会生成一个短寿命的Access Token(简称AT)和一个长寿命的Refresh Token(简称RT) ;要是验证失败,就返回错误信息。
- 返回结果:验证成功后,后端把AT和RT返回给前端;验证失败时,返回
401 Unauthorized
,前端接收到后显示错误消息。 - 前端存储:前端接收到AT和RT后,将它们安全地存储起来,登录成功,用户就可以进入系统了。
(二)访问受保护的API
- 前端请求:前端向需要授权的API发起请求,在请求头的
Authorization
字段里带上Bearer <Access Token>
。 - 后端验证:后端收到请求后,会对Access Token进行验证,主要检查它的签名是否有效、有没有过期,以及权限范围是否符合要求。
- 结果处理:如果Access Token有效,后端就正常处理请求,返回业务数据,前端接收到数据后正常显示;要是Access Token无效或者过期了,后端会返回
401 Unauthorized
,并且在响应体里附带错误代码或消息,明确告诉前端是Token过期导致的问题。
(三)Token刷新流程
- 前端拦截:前端通过配置HTTP响应拦截器(例如使用
axios.interceptors.response.use
)来捕获所有的响应。当拦截器捕获到后端返回的401 Unauthorized
错误,并且确认是Token过期导致的,就会暂停原始请求的失败处理。 - 检查刷新令牌:拦截器会检查本地是否存储了Refresh Token。如果有,就向后端特定的刷新接口
/refresh
发送请求,并在请求体或请求头里带上Refresh Token。 - 后端验证:后端接收到刷新请求后,会验证Refresh Token的有效性。
- 返回结果及前端处理:如果Refresh Token有效,后端会生成新的Access Token,还可能生成新的Refresh Token,然后返回给前端。前端接收到新的令牌后,更新本地存储的令牌,并用新的Access Token重新发送之前失败的那个原始API请求;要是Refresh Token无效或过期,后端返回错误(比如
401
或403
),前端收到错误后,清除本地存储的所有Token,然后把用户重定向到登录页面。
(四)异常处理流程
当多个API请求同时因为Access Token过期收到401
错误时,为了避免同时发起多个刷新请求,前端拦截器需要增加一个状态标记,比如isRefreshing = false
。第一个收到401
的请求会发起/refresh
调用,并把isRefreshing
设为true
。后续收到401
的请求发现isRefreshing
为true
时,就不发起新的/refresh
请求,而是进入一个等待队列(通常用Promise来实现)。当第一个/refresh
请求成功返回后,更新Token,把isRefreshing
设为false
,然后逐一用新的Token重试等待队列中的请求;如果/refresh
请求失败,同样把isRefreshing
设为false
,拒绝等待队列中的请求,引导用户重新登录。
三、技术实现要点
(一)前端实现要点
- 使用HTTP客户端库:像
axios
这样的HTTP客户端库,利用它的拦截器功能是实现无感刷新的关键。通过拦截器,我们可以方便地处理请求和响应,实现Token的自动刷新。 - 安全存储Token:选择合适的存储方式来保存Access Token和Refresh Token,保障用户信息的安全。
- 处理并发请求:实现并发请求处理逻辑,避免在Access Token过期时多次发起刷新请求,确保系统的稳定性。
(二)后端实现要点
- 使用相关库生成和验证Token:在后端可以使用Spring Security和JWT(JSON Web Token)库(比如
jjwt
)来生成和验证Token。 - 提供核心接口:提供三个核心接口,分别是
/login
(用于用户名密码登录,返回Access Token和Refresh Token )、/refresh
(接收Refresh Token,验证通过后返回新的Access Token和可选的新的Refresh Token ),以及受保护的API端点(需要验证请求头中的Access Token )。 - 配置Spring Security:配置Spring Security,明确哪些端点需要认证,哪些不需要。比如
/login
和/refresh
通常允许匿名访问,但/refresh
内部会验证RT。 - 返回明确错误信息:在返回
401
时,最好能提供清晰的错误信息,区分是“Token过期”“无效Token”还是其他认证失败的原因,方便前端进行针对性处理。
通过以上对双Token无感刷新全流程的拆解,希望大家对它有了更清晰的认识。