使用ssl的Spring 5 WebClient

问题描述 投票:10回答:3

我正在尝试查找WebClient使用的示例。我的目标是使用Spring 5 WebClient使用https和自签名证书查询REST服务

任何例子?

spring ssl reactive-programming self-signed spring-webflux
3个回答
13
投票

请参阅使用insecure TrustManagerFactory的示例,该@Bean public WebClient createWebClient() throws SSLException { SslContext sslContext = SslContextBuilder .forClient() .trustManager(InsecureTrustManagerFactory.INSTANCE) .build(); ClientHttpConnector httpConnector = HttpClient.create().secure { t -> t.sslContext(sslContext) } return WebClient.builder().clientConnector(httpConnector).build(); } 信任所有X.509证书(包括自签名)而无需任何验证。文档中的重要说明:

切勿在生产中使用此TrustManagerFactory。它纯粹是出于测试目的,因此非常不安全。

HttpClientOptions

9
投票

看起来像Spring 5.1.1(Spring boot 2.1.0)从ReactorClientHttpConnector中删除了ReactorClientHttpConnector,因此在创建val sslContext = SslContextBuilder .forClient() .trustManager(InsecureTrustManagerFactory.INSTANCE) .build() val httpClient = HttpClient.create().secure { t -> t.sslContext(sslContext) } val webClient = WebClient.builder().clientConnector(ReactorClientHttpConnector(httpClient)).build() 实例时无法配置选项

现在可以使用的一个选项是:

ReactorClientHttpConnector

基本上在创建HttpClient时,我们正在配置不安全的sslContext,然后传递此httpClient以在全局TcpClient中使用。

另一个选项是使用不安全的sslContext配置HttpClient并使用它来创建val sslContext = SslContextBuilder .forClient() .trustManager(InsecureTrustManagerFactory.INSTANCE) .build() val tcpClient = TcpClient.create().secure { sslProviderBuilder -> sslProviderBuilder.sslContext(sslContext) } val httpClient = HttpClient.from(tcpClient) val webClient = WebClient.builder().clientConnector(ReactorClientHttpConnector(httpClient)).build() 实例,如下所示:

https://docs.spring.io/spring/docs/5.1.1.RELEASE/spring-framework-reference/web-reactive.html#webflux-client-builder-reactor

欲获得更多信息:

  • https://netty.io/4.0/api/io/netty/handler/ssl/util/InsecureTrustManagerFactory.html
  • import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; . . . @Bean WebClientCustomizer configureWebclient(@Value("${server.ssl.trust-store}") String trustStorePath, @Value("${server.ssl.trust-store-password}") String trustStorePass, @Value("${server.ssl.key-store}") String keyStorePath, @Value("${server.ssl.key-store-password}") String keyStorePass, @Value("${server.ssl.key-alias}") String keyAlias) { return (WebClient.Builder webClientBuilder) -> { SslContext sslContext; final PrivateKey privateKey; final X509Certificate[] certificates; try { final KeyStore trustStore; final KeyStore keyStore; trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(new FileInputStream(ResourceUtils.getFile(trustStorePath)), trustStorePass.toCharArray()); keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(new FileInputStream(ResourceUtils.getFile(keyStorePath)), keyStorePass.toCharArray()); List<Certificate> certificateList = Collections.list(trustStore.aliases()) .stream() .filter(t -> { try { return trustStore.isCertificateEntry(t); } catch (KeyStoreException e1) { throw new RuntimeException("Error reading truststore", e1); } }) .map(t -> { try { return trustStore.getCertificate(t); } catch (KeyStoreException e2) { throw new RuntimeException("Error reading truststore", e2); } }) .collect(Collectors.toList()); certificates = certificateList.toArray(new X509Certificate[certificateList.size()]); privateKey = (PrivateKey) keyStore.getKey(keyAlias, keyStorePass.toCharArray()); Certificate[] certChain = keyStore.getCertificateChain(keyAlias); X509Certificate[] x509CertificateChain = Arrays.stream(certChain) .map(certificate -> (X509Certificate) certificate) .collect(Collectors.toList()) .toArray(new X509Certificate[certChain.length]); sslContext = SslContextBuilder.forClient() .keyManager(privateKey, keyStorePass, x509CertificateChain) .trustManager(certificates) .build(); HttpClient httpClient = HttpClient.create() .secure(sslContextSpec -> sslContextSpec.sslContext(sslContext)); ClientHttpConnector connector = new ReactorClientHttpConnector(httpClient); webClientBuilder.clientConnector(connector); } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException | UnrecoverableKeyException e) { throw new RuntimeException(e); } }; }

5
投票

不得不编辑这个,以适应spring-boot 2.0-> 2.1的变化。

另一种方法,如果你想编写生产代码,就是创建一个这样的spring bean,它使用spring-boot服务器中的信任库和密钥库所在的设置来修改注入的webclient。在客户端中,如果使用2-way-ssl,则只需要提供密钥库。不确定,为什么ssl-stuff没有预配置且易于注入,类似于非常酷的spring-boot服务器设置。

@Component
public class ClientComponent {

  public ClientComponent(WebClient.Builder webClientBuilder, @Value("${url}") String url) {
    this.client = webClientBuilder.baseUrl(solrUrl).build();
  }
}

这里是您使用Webclient的部分:import org.springframework.web.reactive.function.client.WebClient;

qazxswpoi
© www.soinside.com 2019 - 2024. All rights reserved.