背景
本文是《Java 后端从小白到大神》修仙系列之框架学习,Spring Cloud 微服务实战系列的 第六篇
。Spring Cloud 是构建微服务架构的基石,拥有完整的服务治理生态,在云原生架构中广泛应用。本系列将从架构认知到实际工程,逐步构建一套企业级 Spring Cloud 微服务项目。若想详细学习请点击首篇博文开始,现在开始学习。
文章概览
微服务安全体系设计:JWT + 网关鉴权 + 上下文传递:
- JWT 基础结构与签名机制
- 登录服务颁发 Token + 过期策略设计
- Gateway 中统一认证与白名单机制
- Feign 请求中的 Token 透传机制
- 用户上下文统一提取与安全注入模型
1. JWT 基础结构与签名机制
JWT 即 JSON Web Token,由 Header + Payload + Signature 组成:
- Header: 声明签名算法 (HS256)
- Payload: 包含用户 ID,角色,账号类型
- Signature: 加密(Header + Payload + 私钥)
使用 JWT 可以无独缓存 Token,分布式无依赖,适合微服务。
2. 登录服务符发 Token 和过期策略
在 auth-service 服务中,进行用户合法性校验后,输出 JWT Token:
1
2
3
4
5
6
|
String token = Jwts.builder()
.setSubject(userId)
.setIssuedAt(new Date())
.setExpiration(DateUtil.offsetHour(new Date(), 2))
.signWith(SignatureAlgorithm.HS256, secretKey)
.compact();
|
策略推荐:
- 短效 Token (2h) + RefreshToken 刷新
- 前端随身保存,后端无独缓存
3. Gateway 网关统一鉴权 + 白名单
在 gateway-service 中通过 GlobalFilter 扩展:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
@Component
public class AuthFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String path = exchange.getRequest().getPath().toString();
if (whiteList.contains(path)) return chain.filter(exchange);
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
if (JwtUtil.validate(token)) {
String userId = JwtUtil.extractUserId(token);
exchange.getRequest().mutate().header("X-User-Id", userId);
return chain.filter(exchange);
} else {
return unauthorized(exchange);
}
}
}
|
4. Feign 中 Token 送出 (上下文传递)
通过 user-api 模块公用 Feign 抽象,在下游服务中得到 Token 信息。
1
2
3
4
5
6
7
8
9
|
@Configuration
public class FeignInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
String token = RequestContextHolder.getRequestAttributes()
.getAttribute("Authorization", RequestAttributes.SCOPE_REQUEST);
if (token != null) template.header("Authorization", token.toString());
}
}
|
5. 用户上下文统一接入:SecurityContext
通过 ThreadLocal 和 Filter 解析 token,在 user-service/task-service 中统一输入:
1
2
3
4
5
6
7
8
9
10
11
12
|
public class UserContextFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String token = request.getHeader("Authorization");
if (JwtUtil.validate(token)) {
UserDTO user = JwtUtil.parse(token);
UserContext.set(user);
}
chain.doFilter(request, response);
}
}
|
应用于 Controller / Feign fallback / RabbitMQ 解耦等场景。
总结
本篇以创建 auth-service 为实例
- auth-service: 进行 JWT Token 登录证明
- gateway-service: 增加 GlobalFilter 校验 + header 送出
- user-api: 增加 FeignInterceptor 扩展
- user-service / task-service: 未创建,待后篇实现
至此、一套经过 JWT 签名,网关转发,上下文添加和 Feign 传递的安全化模型已实现,为后续的链路跟踪,分布式交易,统一日志打了基础。