使用账号密码认证后,如何在后续API调用中使用BearerToken及实现建议
问题解答
1. 自定义AuthenticationToken存入SecurityContext是否合理?
这个做法完全合理,属于Spring Security体系下的标准实践。SecurityContext的核心作用就是存储当前请求的认证上下文,自定义AuthenticationToken(继承UsernamePasswordAuthenticationToken是可行的,因为它实现了Authentication接口)可以扩展携带access token、过期时间等业务所需字段,能被SecurityContextHolder正常管理。
注意:如果是多实例分布式部署,默认的ThreadLocal存储的SecurityContext只能在当前请求线程生效,此时需要配合Redis等分布式缓存持久化SecurityContext,否则用户跨实例请求会丢失认证状态。
2. Token存储方案推荐
根据应用架构分场景选择:
- 单体Web应用:
- 优先将带token的AuthenticationToken存入SecurityContext,同时可把token和过期时间存入
HttpSession,会话有效期内用户刷新页面或发起请求时,能从Session恢复认证信息。 - 也可将token存入HttpOnly + Secure属性的Cookie,相比localStorage更安全,能防范XSS攻击窃取token。
- 优先将带token的AuthenticationToken存入SecurityContext,同时可把token和过期时间存入
- 分布式应用:
- 不能依赖HttpSession,建议将包含token、过期时间的认证信息存入Redis,设置与token过期时间一致的Key有效期。前端每次请求携带会话标识(如sessionId),后端从Redis中取出对应token信息。
3. 请求前验证token过期的实现方式
推荐通过Spring Security的自定义Filter统一处理,避免重复代码:
- 自定义
TokenValidationFilter继承OncePerRequestFilter,在doFilterInternal方法中执行:- 从SecurityContext/Redis/Session/Cookie中获取AuthenticationToken及过期时间。
- 对比当前时间与token过期时间,若已过期则清除SecurityContext认证信息,返回401或跳转登录页。
- 未过期则放行,继续执行后续过滤器链。
- 将该Filter配置在Spring Security过滤器链中,放在认证过滤器之后、业务接口之前。
也可在API调用工具类中添加验证逻辑,但Filter方式更统一,适合全局生效。
额外建议
- 必须在后端存储并验证token过期时间,禁止仅依赖前端存储的过期信息,防止篡改绕过验证。
- 若API支持refresh token,可在token即将过期时自动调用刷新接口获取新access token,提升用户体验;refresh token需存入更安全的位置(如HttpOnly Cookie),且设置更长的过期时间。
- 自定义AuthenticationToken时,建议重写
isAuthenticated()方法,除判断认证状态外,加入token是否过期的校验,让Spring Security默认认证逻辑能感知过期状态。
内容的提问来源于stack exchange,提问作者Kalry
相关产品推荐
相关产品推荐

