文章

Spring Security 和 JWT 在微服务认证中的协作方式

语之溪

·

Java

·

⚠️ 本文最后更新于2026年02月07日,已经过了198天没有更新,若内容或图片失效,请留言反馈

JWT 解决的是凭证格式和签名验证,Spring Security 解决的是请求如何进入安全过滤链、身份如何放入安全上下文,以及接口怎样根据认证与权限做出决定。

在微服务认证中,两者需要配合,但不能把所有事情都归给 JWT。登录、令牌签发、网关校验、业务权限和会话撤销分别属于不同边界。

Spring Security 负责什么

Spring Security 提供一套认证与授权框架,主要关注:

  • 请求经过哪些安全过滤器;
  • 如何提取认证信息;
  • 认证成功后怎样建立安全上下文;
  • 未认证和权限不足怎样返回;
  • 哪些路径公开,哪些路径受保护;
  • 方法或接口怎样判断角色与权限。

它并不要求必须使用 JWT。JWT 只是其中一种身份凭证方案。

JWT 负责什么

JWT 可以携带一组声明,并通过签名防止内容被未授权修改。

Header
Payload
Signature

常见声明包括签发者、主题、签发时间、过期时间和令牌类型。业务需要的用户标识或角色信息可以适量放入,但不能把密码、隐私数据和频繁变化的大量权限都塞进 Token。

签名只能证明令牌内容在持有密钥的一方签发后没有被篡改,不能证明持有者一定是本人,也不能自动处理撤销和账号状态变化。

登录发生在认证服务

登录接口通常由认证服务处理:

提交账号与凭据
    -> Spring Security 认证流程
    -> 查询用户与账号状态
    -> 校验密码
    -> 生成 Access Token
    -> 生成 Refresh Token
    -> 保存必要的服务端状态

密码应使用合适的单向散列算法保存,不能与 JWT 签名密钥混为一谈。

认证失败时应返回统一但不过度详细的信息,避免暴露账号是否存在、密码策略或内部异常。

普通请求怎样经过网关

客户端访问业务接口时,通常携带 Access Token。

客户端
    -> Gateway 安全过滤链
    -> 提取 Bearer Token
    -> 验证格式、签名和有效期
    -> 检查必要状态
    -> 清理客户端伪造身份头
    -> 传递可信身份到下游

网关可以完成基础身份验证和受保护路由判断,但不应该掌握所有业务数据权限。

例如“用户是否能编辑这个视频”需要结合视频所有者、审核状态和管理员权限,应该由内容服务根据业务数据判断。

Spring Security 过滤链的位置

在 Web 应用中,安全过滤器会在请求到达 Controller 前执行。

一个简化的 JWT 过滤器逻辑可以表示为:

String token = resolveToken(request);
if (token != null && tokenService.isValid(token)) {
    Authentication authentication = tokenService.parseAuthentication(token);
    SecurityContextHolder.getContext().setAuthentication(authentication);
}
filterChain.doFilter(request, response);

这是通用示例,不是 HAOVP 的真实实现,也没有展示完整异常处理和安全配置。

过滤器需要避免:

  • 对公开路径强制要求 Token;
  • Token 无效后仍建立认证上下文;
  • 在日志中打印完整 Token;
  • 忘记清理或隔离请求安全上下文;
  • 把业务权限判断塞进基础认证过滤器。

下游服务是否还要校验

如果所有外部请求都经过可信网关,下游可以接收网关传递的身份信息,但要防止服务被绕过网关直接访问。

可以考虑:

  • 网络层只允许受控入口访问业务服务;
  • 服务间请求使用内部身份或签名;
  • 下游验证网关注入的身份头来源;
  • 对敏感操作进行必要的二次校验;
  • 业务服务始终校验具体资源权限。

“网关已经验过 Token”不能等同于“业务服务不需要授权”。认证回答是谁,授权回答能做什么。

Redis 在认证中的作用

JWT 可以离线验证签名,但项目仍可能需要 Redis 保存会话和撤销相关状态,例如:

  • Refresh Token 标识或哈希;
  • 登录会话状态;
  • Token 黑名单;
  • 用户令牌版本;
  • 验证码;
  • 失败次数和临时限制;
  • 强制退出标记。
JWT:携带短期身份声明
Redis:维护需要即时变化的认证状态

是否每次请求都查询 Redis,要看即时撤销要求、性能和复杂度。完全查询会增加状态依赖,完全不查询则无法立即响应部分账号变化。

账号状态变化如何生效

用户被禁用、修改密码或退出所有设备后,旧 Access Token 可能仍在有效期内。

常见处理方向包括:

  • 缩短 Access Token 有效期;
  • 撤销 Refresh Token,阻止续期;
  • 使用用户令牌版本;
  • 对敏感操作查询最新账号状态;
  • 使用黑名单处理需要立即失效的令牌。

每种方式都有额外存储或查询成本,需要根据风险决定。

角色和权限放多少进 JWT

把角色放入 JWT 可以减少查询,但角色变化后旧 Token 中的信息不会立即更新。

我会区分:

  • 稳定且粗粒度的身份信息;
  • 频繁变化的业务权限;
  • 与具体数据记录相关的资源权限。

前者可以适量放入 Token,后两者更适合由业务服务实时判断。管理操作尤其不能只依赖一个长期不变的角色声明。

错误边界要清楚

认证和授权失败需要区分:

未携带或无效凭证 -> 401
身份有效但没有权限 -> 403
业务状态不允许操作 -> 业务错误
下游服务不可用 -> 服务可用性错误

如果所有情况都返回 401,客户端无法判断应该刷新凭证、重新登录还是提示无权限。

错误响应中可以带请求标识帮助排查,但不能返回签名密钥、完整 Token 和内部堆栈。

Security 配置需要显式检查

安全配置中容易遗漏:

  • 健康检查和登录接口是否正确放行;
  • 管理接口是否使用更严格规则;
  • CSRF 是否根据实际认证方式处理;
  • CORS 是否与网关配置一致;
  • Session 是否无意中被创建;
  • 异常处理器是否返回统一结构;
  • 方法级权限是否真正启用;
  • 测试环境是否错误地放宽全部接口。

配置能够启动不代表安全边界正确,需要使用不同身份和异常场景验证。

Spring Security 与 JWT 的协作方式,可以概括为:认证服务使用 Spring Security 完成登录和签发,JWT 承载短期身份,网关通过安全过滤链验证基础凭证,Redis维护需要即时变化的状态,业务服务判断具体权限。

这套分工减少了职责混杂,但仍要通过令牌失效、权限变化、绕过网关和异常响应等场景持续验证。安全不是某个依赖自动提供的结果,而是多层边界共同成立。

现在已有 9 次阅读,0 条评论,0 人点赞
作者:语之溪
作者
Spring Security 和 JWT 在微服务认证中的协作方式
当前文章累计共 3059 字,阅读大概需要 5 分钟。
Docker 容器开机自动启动
2023年7月3日 - 0评论
我如何使用 Codex 开始开发 HAOVP
2025年12月27日 - 0评论
一次在线视频平台接口验收记录
2026年4月25日 - 0评论
评论:共0条
发表
搜索 消息 足迹 排行
你还不曾留言过..
你还不曾留下足迹..
博主 不再显示
博主
未知作品 歌曲封面
立即安装