Spring微服务中如何在OpenAPI生成的WebClient传递Authorization Header
针对你用OpenAPI Generator生成服务A的WebClient客户端、需要将服务A收到的OAuth2 Authorization头动态传递给服务B的场景,提供以下三种可行方案:
方案一:让生成的客户端方法支持传入Authorization头
通过调整OpenAPI定义和生成配置,让客户端API方法直接接收Authorization头参数,手动传递:
- 调整服务B的OpenAPI定义
在服务B的OpenAPI YAML中声明OAuth2安全方案,并给需要授权的接口添加安全要求:
components: securitySchemes: OAuth2Auth: type: http scheme: bearer bearerFormat: JWT security: - OAuth2Auth: []
- 配置OpenAPI Generator生成带Header参数的方法
如果用Maven插件生成客户端,添加useRequestHeaders等配置,确保方法支持传入自定义Header:
<plugin> <groupId>org.openapitools</groupId> <artifactId>openapi-generator-maven-plugin</artifactId> <version>6.6.0</version> <!-- 使用最新稳定版本 --> <executions> <execution> <goals> <goal>generate</goal> </goals> <configuration> <inputSpec>${project.basedir}/src/main/resources/openapi/service-b.yaml</inputSpec> <generatorName>spring</generatorName> <configOptions> <library>webclient</library> <useRequestHeaders>true</useRequestHeaders> <interfaceOnly>true</interfaceOnly> <!-- 可选,仅生成接口便于自定义实现 --> </configOptions> </configuration> </execution> </executions> </plugin>
- 在服务A中手动传递Header
在服务A的Controller中获取当前请求的Authorization头,调用服务B客户端时传入:
@RestController public class ServiceAController { private final ServiceBApi serviceBApi; public ServiceAController(ServiceBApi serviceBApi) { this.serviceBApi = serviceBApi; } @GetMapping("/public-endpoint") public ResponseEntity<?> handlePublicRequest( @RequestHeader("Authorization") String authHeader, @RequestParam String businessParam) { // 处理业务逻辑 // 调用服务B的接口,传入Authorization头 MultiValueMap<String, String> headers = new LinkedMultiValueMap<>(); headers.add("Authorization", authHeader); ServiceBResponse response = serviceBApi.targetEndpoint(headers, businessParam).block(); return ResponseEntity.ok(response); } }
方案二:通过WebClient过滤器自动传递Header
无需手动在每个方法传参,通过全局过滤器自动从服务A的请求上下文提取Authorization头,添加到服务B的请求中:
1. 同步场景(Spring MVC)
创建过滤器类:
@Component public class AuthHeaderPropagationFilter implements ExchangeFilterFunction { @Override public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) { // 从当前请求上下文获取Authorization头 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (attributes == null) { return next.exchange(request); } String authHeader = attributes.getRequest().getHeader("Authorization"); if (authHeader != null) { ClientRequest modifiedRequest = ClientRequest.from(request) .header("Authorization", authHeader) .build(); return next.exchange(modifiedRequest); } return next.exchange(request); } }
覆盖生成的WebClient配置,添加过滤器:
@Configuration @Primary public class CustomServiceBApiConfig extends ServiceBApiConfiguration { private final AuthHeaderPropagationFilter authFilter; public CustomServiceBApiConfig(AuthHeaderPropagationFilter authFilter) { this.authFilter = authFilter; } @Override public WebClient webClient(WebClient.Builder webClientBuilder) { return webClientBuilder .filter(authFilter) .baseUrl("${service-b.base-url:http://localhost:8081}") .build(); } }
2. 响应式场景(Spring WebFlux)
调整过滤器适配响应式上下文:
@Component public class ReactiveAuthHeaderPropagationFilter implements ExchangeFilterFunction { @Override public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) { return Mono.deferContextual(contextView -> { ServerWebExchange exchange = contextView.getOrDefault(ServerWebExchange.class, null); if (exchange == null) { return next.exchange(request); } String authHeader = exchange.getRequest().getHeaders().getFirst("Authorization"); if (authHeader != null) { ClientRequest modifiedRequest = ClientRequest.from(request) .header("Authorization", authHeader) .build(); return next.exchange(modifiedRequest); } return next.exchange(request); }); } }
在服务A的响应式Controller中传递上下文:
@RestController public class ServiceAController { private final ServiceBApi serviceBApi; public ServiceAController(ServiceBApi serviceBApi) { this.serviceBApi = serviceBApi; } @GetMapping("/public-endpoint") public Mono<ResponseEntity<?>> handlePublicRequest(ServerWebExchange exchange) { return serviceBApi.targetEndpoint() .contextWrite(context -> context.put(ServerWebExchange.class, exchange)) .map(ResponseEntity::ok); } }
方案三:自定义OpenAPI Generator模板(高级)
如果上述方案不满足需求,可以修改Generator的Mustache模板(如api.mustache),让生成的客户端代码自动注入Header传递逻辑。但该方案维护成本较高,仅推荐有定制化需求的场景。
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

