You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring微服务中如何在OpenAPI生成的WebClient传递Authorization Header

动态传递Authorization头到OpenAPI生成的WebClient客户端

针对你用OpenAPI Generator生成服务A的WebClient客户端、需要将服务A收到的OAuth2 Authorization头动态传递给服务B的场景,提供以下三种可行方案:

方案一:让生成的客户端方法支持传入Authorization头

通过调整OpenAPI定义和生成配置,让客户端API方法直接接收Authorization头参数,手动传递:

  1. 调整服务B的OpenAPI定义
    在服务B的OpenAPI YAML中声明OAuth2安全方案,并给需要授权的接口添加安全要求:
components:
  securitySchemes:
    OAuth2Auth:
      type: http
      scheme: bearer
      bearerFormat: JWT
security:
  - OAuth2Auth: []
  1. 配置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>
  1. 在服务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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 03:01:12