如何在Spring Boot WebClient中实现HTTPS双向认证及Bearer Token管理?
Spring WebFlux后端实现双向HTTPS+OAuth2客户端凭证授权流程
一、OAuth2客户端凭证模式配置(自动获取Bearer Token)
首先引入OAuth2客户端依赖(基于Spring Boot):
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency>
在application.yml中配置认证服务器信息与客户端凭证:
spring: security: oauth2: client: registration: business-server-client: client-id: YOUR_CLIENT_ID client-secret: YOUR_CLIENT_SECRET authorization-grant-type: client_credentials provider: business-server-client: token-uri: https://auth-server.example.com/oauth2/token
配置WebClient时,集成OAuth2授权客户端管理器,实现自动获取并携带Token:
@Configuration public class WebClientConfig { @Bean public WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) { ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Filter = new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager); oauth2Filter.setDefaultClientRegistrationId("business-server-client"); return WebClient.builder() .filter(oauth2Filter) .build(); } @Bean public OAuth2AuthorizedClientManager authorizedClientManager( ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientService authorizedClientService) { OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder() .clientCredentials() .build(); DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager( clientRegistrationRepository, authorizedClientService); authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); return authorizedClientManager; } }
二、双向HTTPS连接配置
准备客户端证书:将业务服务器信任的客户端证书打包为JKS/P12格式,放置在项目资源目录下。
在
application.yml中添加SSL配置:
server: ssl: # 客户端证书密钥库(双向认证用) key-store: classpath:client-cert.p12 key-store-password: YOUR_KEY_STORE_PWD key-store-type: PKCS12 # 信任业务服务器证书的信任库 trust-store: classpath:trust-store.jks trust-store-password: YOUR_TRUST_STORE_PWD trust-store-type: JKS # 启用双向认证 client-auth: need
- 为
WebClient配置SSL上下文,确保请求业务服务器时使用客户端证书:
@Configuration public class WebClientSslConfig { @Value("${server.ssl.key-store}") private Resource keyStore; @Value("${server.ssl.key-store-password}") private String keyStorePassword; @Value("${server.ssl.trust-store}") private Resource trustStore; @Value("${server.ssl.trust-store-password}") private String trustStorePassword; @Bean public SslContext sslContext() throws Exception { KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance( KeyManagerFactory.getDefaultAlgorithm()); keyManagerFactory.init( KeyStore.getInstance(keyStore.getInputStream()), keyStorePassword.toCharArray()); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init( KeyStore.getInstance(trustStore.getInputStream()), trustStorePassword.toCharArray()); return SslContextBuilder.forClient() .keyManager(keyManagerFactory) .trustManager(trustManagerFactory) .build(); } @Bean public ClientHttpConnector clientHttpConnector(SslContext sslContext) { return new ReactorClientHttpConnector(HttpClient.create().secure(t -> t.sslContext(sslContext))); } }
三、整合配置:请求业务服务器时同时启用双向认证与Token携带
修改之前的WebClient配置,注入ClientHttpConnector:
@Configuration public class WebClientConfig { @Bean public WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager, ClientHttpConnector clientHttpConnector) { ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Filter = new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager); oauth2Filter.setDefaultClientRegistrationId("business-server-client"); return WebClient.builder() .clientConnector(clientHttpConnector) .filter(oauth2Filter) .build(); } // 省略authorizedClientManager配置... }
使用示例
通过配置好的WebClient请求业务服务器,会自动完成双向HTTPS认证与Bearer Token的携带:
@Service public class BusinessService { private final WebClient webClient; public BusinessService(WebClient webClient) { this.webClient = webClient; } public Mono<String> fetchBusinessData() { return webClient.get() .uri("https://business-server.example.com/api/data") .retrieve() .bodyToMono(String.class); } }
内容的提问来源于stack exchange,提问作者cknelle
相关产品推荐
相关产品推荐

