跳到主要内容

微服务安全

问题

微服务架构下如何做认证鉴权?服务间调用如何保证安全?常见的安全方案有哪些?

答案

微服务安全架构

认证方案

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 怎么在服务间传递?

答案

  1. 网关验证 JWT 后,将用户信息(userId、role)放入 HTTP Header
  2. 下游服务从 Header 中获取用户信息
  3. 服务间调用(Feign)通过拦截器自动传递 Header

注意:不要在 Header 中传递敏感信息(如密码),只传递必要的身份标识。

Q3: 如何防止内部 API 被外部直接访问?

答案

  1. 网络隔离:内部服务不暴露公网端口,只在 K8s Service 网络内可达
  2. 网关拦截:所有外部请求必须经过网关,网关验证后添加内部标识 Header
  3. 服务端校验:内部服务检查请求是否来自网关(判断内部 Header)

相关链接