基于 Access Token 和 Refresh Token实现无感刷新
双 Token 原理概述
- Access Token:短期有效(如 30 分钟),用于接口鉴权,存放用户身份与权限信息。
- Refresh Token:长期有效(如 7 天),仅用于在 Access Token 过期后“换取”新的两个 Token。
- 无感刷新:用户在 Access Token 过期后,客户端自动携带 Refresh Token 请求刷新,服务器验证 Refresh Token 后下发新的 Access/Refresh Token,用户无须重新登录。
登录与颁发流程
客户端提交用户名/密码 → 服务端验证。
验证通过后:
- 创建 Access Token,设置 30 分钟过期;
- 创建 Refresh Token,设置 7 天过期;
将两者封装返回给客户端:
1
2
3
4
5
6{
"accessToken": "eyJhbGci…",
"accessExpire": 162…,
"refreshToken": "eyJhbGc…",
"refreshExpire": 162…
}
访问拦截与刷新流程
接口访问
客户端在每次请求
Authorization: Bearer <accessToken>服务端拦截器解析 Access Token:
- 未过期 → 正常放行;
- 已过期 → 返回特定状态码 401/511。
无感刷新
- 客户端拦截到 401/511 → 同步或异步调用刷新接口
- 服务端验证 Refresh Token:
- 合法且未过期 → 重新生成 Access & Refresh Token 并返回;
- 非法或已过期 → 返回 403 → 客户端跳转登录。
- 客户端更新本地存储中的两个 Token,并重试原请求。
安全性与性能考虑
- 防重放:Refresh Token 一旦使用即作废,服务端持久化黑名单或单次使用策略。
- 漏洞防护:将 Refresh Token 存放在 HttpOnly Cookie 中,避免 XSS 泄露。
- 并发刷新:客户端应保证同一时刻只有一次刷新调用,避免请求风暴。
- 性能监控:统计刷新接口调用量,异常时及时报警。
为什么 Authorization 头要写成 Bearer <token>?
这是HTTP 标准规定的身份验证格式。HTTP 协议里,Authorization 头支持多种认证方式,服务器必须知道你用的是哪一种。
常见的认证类型(服务器必须区分)
Basic:基础认证(账号密码 base64)Digest:摘要认证Bearer:OAuth2 / JWT 令牌认证AWS4-HMAC-SHA256:AWS 签名- 等等…
HttpOnly Cookie 到底是什么?
HttpOnly Cookie = 浏览器给你存的、JS 完全碰不到的、最安全的身份凭证
后端发给浏览器,前端无感
1
2
3
4
5
6Cookie cookie = new Cookie("token", "你的JWT令牌");
cookie.setHttpOnly(true); // 核心
cookie.setSecure(true);
cookie.setPath("/");
cookie.setMaxAge(86400);
response.addCookie(cookie);浏览器自动保存
JS 代码读不到、改不了 → 防 XSS 偷 token
下次发请求浏览器自动带上 → 不用写代码加请求头
后端验证它
只能是refreshToken设置HttpOnly ,因为前端需要访问到accessToken,来判定过期时间等。