共计 2361 个字符,预计需要花费 6 分钟才能阅读完成。
当页面突然弹出 ” 无 token,请重新登录 ”
每个开发者都见过这个场景:用户正在操作时,界面突然弹出 {"code":401,"msg":"无 token,请重新登录","data":null} 的提示。这个 HTTP 401 未授权错误(Unauthorized)会打断用户流程,直接影响产品体验。统计显示,认证失败导致的用户流失率高达 23%,其中 401 错误占比 67%。

认证机制的技术本质
HTTP 认证流程图解
sequenceDiagram
Client->>Server: 请求敏感数据
Server-->>Client: 401 Unauthorized + WWW-Authenticate 头
Client->>Server: 携带 Authorization 头
Server-->>Client: 200 OK/403 Forbidden
JWT vs Session 认证对比
| 维度 | JWT(JSON Web Token) | Session |
|---|---|---|
| 存储位置 | 客户端 | 服务端 |
| 扩展性 | 天然支持分布式 | 需要共享存储 |
| 安全性 | 依赖签名算法 | 依赖 Session ID 保密性 |
| 性能影响 | 每次请求需验证签名 | 需要查会话存储 |
| 典型失效场景 | Token 泄露难撤回 | 服务端存储溢出 |
401 与 403 的核心区别
- 401 Unauthorized:身份未验证(可能是无效凭证)
- 403 Forbidden:身份已确认但权限不足
从零构建安全认证系统
Spring Security + JWT 实现
// JWT 生成过滤器
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) {String token = resolveToken(request);
if (token != null && jwtProvider.validateToken(token)) {Authentication auth = jwtProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);
}
chain.doFilter(request, response);
}
// 实现 Token 刷新接口
@PostMapping("/refresh-token")
public ResponseEntity refreshToken(@CookieValue String refreshToken) {if (!jwtProvider.validateRefreshToken(refreshToken)) {throw new InvalidJwtException("Refresh token 失效");
}
String newAccessToken = jwtProvider.generateAccessToken(jwtProvider.getUsername(refreshToken));
return ok().body(new TokenResponse(newAccessToken));
}
}
前端 axios 拦截器
// 响应拦截器
axios.interceptors.response.use(
response => response,
async error => {
const originalRequest = error.config;
if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
try {const newToken = await refreshToken();
store.dispatch('updateToken', newToken);
originalRequest.headers.Authorization = `Bearer ${newToken}`;
return axios(originalRequest);
} catch (refreshError) {router.push('/login');
return Promise.reject(refreshError);
}
}
return Promise.reject(error);
}
);
生产环境进阶方案
Token 存储选型对比
- 内存存储(如 ConcurrentHashMap):
- 优点:零网络开销,响应快(平均 0.2ms)
-
缺点:节点间不同步,重启丢失
-
Redis 集群:
- 优点:数据持久化,支持 TTL(测试环境吞吐量可达 15k QPS)
- 缺点:增加网络延迟(平均增加 1.5-3ms)
分布式认证一致性
- 采用 JWT + 短时效(如 15 分钟)
- 敏感操作二次验证
- 黑名单服务用 Redis Pub/Sub 同步
防御 Token 重放攻击
- 请求时间戳校验(窗口期 5 分钟)
- Nonce 随机数一次有效
- 关键操作绑定设备指纹
工程师思维训练
三个经典陷阱
- 无限刷新循环:当 refresh_token 也过期时,未处理降级登录
- 密钥管理不当:将 JWT 密钥硬编码在客户端
- 过度信任 Token:未校验用户状态是否已被封禁
无感刷新设计思考
- 静默刷新时机:可在 Token 到期前 30 秒自动刷新
- 并发请求处理:需要实现请求队列避免重复刷新
- 离线处理:Service Worker 缓存未发送请求
写在最后
HTTP 401 错误只是认证系统的冰山一角,背后需要建立完整的令牌生命周期管理体系。建议在测试环境模拟各种 Token 失效场景,统计 401 错误的发生频率和类型,持续优化认证流程。记住:好的认证系统应该像空气一样——用户感受不到它的存在,但它时刻都在保护安全。
正文完
