Webapp 令牌安全指南:访问与刷新实践
本文详解Web应用中accesstoken与refreshtoken的颁发、存储、使用及自动续期机制,涵盖前后端协作流程、前端存储策略(localStorage/sessionStorage)、HTTP请求头携带方式、过期检测逻辑及推荐的拦截器实现方案。

本文详解 Web 应用中 access token 与 refresh token 的颁发、存储、使用及自动续期机制,涵盖前后端协作流程、前端存储策略(localStorage/sessionStorage)、HTTP 请求头携带方式、过期检测逻辑及推荐的拦截器实现方案。
在现代 Web 应用(尤其是基于 JavaScript 框架如 Angular、React 或 Vue 构建的单页应用)中,采用 Token 认证(如 OAuth 2.0 或 JWT)已成为主流方案。其中,access token(访问令牌)用于短期 API 调用鉴权,而refresh token(刷新令牌)则用于在 access token 过期后安全地获取新令牌,避免用户频繁重新登录。
✅ 标准流程:登录 → 发放 → 存储 → 使用 → 刷新
服务端发放双令牌
用户凭账号密码完成登录后,服务端应生成一对令牌:- access_token:短时效(如 15–60 分钟),签名有效,用于每次 API 请求鉴权;
- refresh_token:长时效(如 7–30 天),强保密(不暴露于前端 JS 环境更佳),仅用于向 /auth/refresh 等专用接口换取新 access token。
两者以 JSON 形式返回客户端,例如:{ "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "refresh_token": "d3a7f9c1-8b2e-4e8a-b4f0-2c1a3e4d5f6b", "expires_in": 900 }
前端安全存储策略
- ❌ 不推荐 Cookie(尤其未设 HttpOnly):若将 access_token 存于普通 Cookie 并通过 withCredentials: true 发送,易受 XSS 攻击窃取;且无法被 JS 读取,导致无法手动添加 Authorization: Bearer
头。 - ✅ 推荐 localStorage / sessionStorage:
- localStorage:持久化存储,浏览器关闭后仍保留 → 适用于“保持登录”场景;
- sessionStorage:仅限当前标签页生命周期 → 更安全,但关闭标签即登出。
示例(登录成功后):// TypeScript(Angular/React/Vue 通用逻辑) localStorage.setItem('access_token', response.access_token); localStorage.setItem('refresh_token', response.refresh_token); localStorage.setItem('expires_at', Date.now() + response.expires_in * 1000);
- ❌ 不推荐 Cookie(尤其未设 HttpOnly):若将 access_token 存于普通 Cookie 并通过 withCredentials: true 发送,易受 XSS 攻击窃取;且无法被 JS 读取,导致无法手动添加 Authorization: Bearer
请求时自动注入 access token
所有需鉴权的 API 请求必须在 Authorization 请求头中携带 access token:Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
实践中,应使用HTTP 拦截器(Interceptor)统一处理,避免每个请求手动添加。以 Angular 为例:
@Injectable() export class AuthInterceptor implements HttpInterceptor { intercept(req: HttpRequest, next: HttpHandler): Observable > { const token = localStorage.getItem('access_token'); if (token) { const authReq = req.clone({ headers: req.headers.set('Authorization', `Bearer ${token}`) }); return next.handle(authReq); } return next.handle(req); } } 自动续期:用户离开又返回时如何“无感登录”?
当用户关闭浏览器后再次访问网站,前端应:- 检查 localStorage 是否存在 access_token 和 refresh_token;
- 验证 access_token 是否过期(解析 JWT payload 中的 exp 字段,或比对本地 expires_at 时间戳);
- ✅ 未过期 → 直接使用,发起请求;
- ⚠️ 已过期 → 使用 refresh_token 向后端 /auth/refresh 接口发起 POST 请求,换取新 access_token(注意:此请求不应携带原 access_token,且需校验 refresh_token 有效性与绑定关系);
- ❌ refresh_token 也过期或无效 → 强制跳转登录页。
? 安全提示:refresh_token 建议由服务端存储在 Redis 等可撤销存储中,并与用户设备指纹/UA/IP 绑定,支持主动吊销(如用户登出、异地登录)。
? 总结与最佳实践
- 双令牌机制是平衡安全性与用户体验的关键设计;
- 前端优先使用 localStorage + 显式过期时间管理,而非依赖 Cookie 自动发送;
- 必须通过 HTTP 拦截器统一注入 token,并集中处理 401 响应(触发刷新逻辑);
- 服务端需提供 /auth/refresh 接口,严格校验 refresh_token,且禁止返回新的 refresh_token(除非启用轮换策略);
- 生产环境务必启用 HTTPS,防止 token 在传输中被劫持。
遵循以上模式,即可构建既安全又流畅的用户会话体验。


































