微服务安全
问题
微服务架构下如何做认证鉴权?服务间调用如何保证安全?常见的安全方案有哪些?
答案
微服务安全架构
认证方案
JWT + 网关统一鉴权
最主流的方案:网关验证 JWT,将用户信息传递给下游服务。
网关层 JWT 过滤器
@Component
public class JwtAuthFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
// 白名单路径跳过
if (isWhiteListed(exchange.getRequest().getPath())) {
return chain.filter(exchange);
}
if (token == null || !token.startsWith("Bearer ")) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
try {
Claims claims = JwtUtil.parseToken(token.substring(7));
// 将用户信息放入 Header 传递给下游
ServerHttpRequest request = exchange.getRequest().mutate()
.header("X-User-Id", claims.getSubject())
.header("X-User-Role", claims.get("role", String.class))
.build();
return chain.filter(exchange.mutate().request(request).build());
} catch (Exception e) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
}
@Override
public int getOrder() { return -100; }
}
下游服务获取用户信息
@RestController
public class OrderController {
@PostMapping("/orders")
public Order createOrder(
@RequestHeader("X-User-Id") String userId,
@RequestHeader("X-User-Role") String role,
@RequestBody OrderDTO dto) {
// 直接使用网关传递的用户信息
return orderService.create(userId, dto);
}
}
OAuth 2.0
适用于第三方接入、开放平台场景。
服务间认证
内部服务之间的调用也需要安全控制,防止非法访问。
| 方案 | 说明 | 适用场景 |
|---|---|---|
| 内部 Token | 服务间传递内部签名 Token | 简单、轻量 |
| mTLS | 双向 TLS 证书认证 | Service Mesh |
| 网络隔离 | 内部服务只在 K8s 集群内可达 | 基础防护 |
Feign 拦截器传递 Token
@Component
public class FeignAuthInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
// 从当前请求上下文中获取用户 Token,传递给下游
ServletRequestAttributes attrs = (ServletRequestAttributes)
RequestContextHolder.getRequestAttributes();
if (attrs != null) {
String token = attrs.getRequest().getHeader("Authorization");
if (token != null) {
template.header("Authorization", token);
}
}
}
}
权限控制
| 方案 | 说明 |
|---|---|
| RBAC | 基于角色的访问控制(最常用) |
| ABAC | 基于属性的访问控制 |
| 网关级别 | 在网关层根据路径 + 角色过滤 |
| 服务级别 | Spring Security @PreAuthorize 注解 |
常见面试问题
Q1: 微服务鉴权放在网关还是各服务?
答案:
分层鉴权:
- 网关层:统一认证(JWT 验证)+ 粗粒度权限(如路径级别的角色校验)
- 服务层:细粒度权限(如按钮级别、数据级别)
网关做认证,服务做授权。这样既减少了各服务重复的认证逻辑,又保留了细粒度控制能力。
Q2: Token 怎么在服务间传递?
答案:
- 网关验证 JWT 后,将用户信息(userId、role)放入 HTTP Header
- 下游服务从 Header 中获取用户信息
- 服务间调用(Feign)通过拦截器自动传递 Header
注意:不要在 Header 中传递敏感信息(如密码),只传递必要的身份标识。
Q3: 如何防止内部 API 被外部直接访问?
答案:
- 网络隔离:内部服务不暴露公网端口,只在 K8s Service 网络内可达
- 网关拦截:所有外部请求必须经过网关,网关验证后添加内部标识 Header
- 服务端校验:内部服务检查请求是否来自网关(判断内部 Header)