ssl을 사용하는 Spring 5 WebClient
Web Client 사용 사례를 찾고 있습니다.
Spring 5 WebClient를 사용하여 https 및 자체 서명 인증서를 사용하여 REST 서비스를 쿼리하는 것이 목표입니다.
예를 들어볼까요?
Spring 5.1.1(Spring boot 2.1.0)이 제거된 것 같습니다.HttpClientOptions부터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()
기본적으로 HttpClient를 생성하는 동안 insecureslContext를 구성한 다음 사용할 httpClient를 전달합니다.ReactorClientHttpConnector세계적으로
다른 옵션은 구성하는 것입니다.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
업데이트: 동일한 코드의 Java 버전
SslContext context = SslContextBuilder.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.build();
HttpClient httpClient = HttpClient.create().secure(t -> t.sslContext(context));
WebClient wc = WebClient
.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient)).build();
확인 없이 모든 X.509 인증서(자체 서명 포함)를 신뢰하는 안전하지 않은 TrustManagerFactory 사용 예를 참조하십시오.설명서의 중요한 참고 사항:
프로덕션에서 이 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();
}
스프링 부트 2.0->2.1 변경 사항을 수용하기 위해 이를 편집해야 했습니다.
프로덕션 코드를 프로그래밍하려는 또 다른 방법은 신뢰 저장소 및 키 저장소가 있는 위치에 대한 스프링 부트 서버의 설정을 사용하여 주입된 WebClient를 수정하는 것입니다.클라이언트에서 2-way-ssl을 사용하는 경우 Keystore만 제공하면 됩니다.ssl-stuff가 정말 멋진 스프링 부트 서버 설정과 유사하게 사전 구성되지 않고 쉽게 주입할 수 없는 이유는 확실하지 않습니다.
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);
}
};
}
웹 클라이언트를 사용하는 부분은 다음과 같습니다.
import org.springframework.web.reactive.function.client.WebClient;
@Component
public class ClientComponent {
public ClientComponent(WebClient.Builder webClientBuilder, @Value("${url}") String url) {
this.client = webClientBuilder.baseUrl(solrUrl).build();
}
}
이것은 나에게 효과가 있습니다.Spring 프레임워크 버전 5.3.23(Spring boot 버전 2.7.4) ReactorClientHttpConnector를 사용하여 다음과 같은 방법을 시도할 수 있습니다.
SslContext context = SslContextBuilder.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.build();
HttpClient httpClient = HttpClient.create().secure(t -> t.sslContext(context));
WebClient wc = WebClient
.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient)).build();
이 대답이 당신에게 도움이 되기를 바랍니다.
반응형 WebFlux webClient를 사용하여 https로 보호되는 REST API를 사용하는 방법을 고수했을 수 있는 사람을 위한 것입니다.
당신은 두 가지를 창조하기를 원합니다.
- https 사용 REST API - https://github.com/mghutke/HttpsEnabled
- 위의 REST API를 사용할 WebClient가 있는 클라이언트로서의 또 다른 REST API - https://github.com/mghutke/HttpsClient
참고: 위의 프로젝트를 통해 위의 스프링 부트 앱과 공유된 키 저장소를 확인하십시오.그리고 프로그래밍 방식으로 키 매니저 팩토리와 트러스트 매니저 팩토리를 추가했습니다.
또한 예를 들어 여러 SSL 컨텍스트를 구성해야 하는 경우 REST API 1과 REST API 2가 있으며 이를 위해 구성했습니다.SSLContext sslContext1그리고.SSLContext sslContext2
중요한 것은HttpClient.create().secure(...)하나만 적용할 수 있습니다.SSLContext하지만 우리의 경우에는 여러 개를 원합니다.
그래서, 우리의 경우의 해결책은 두 개의 다른 것을 만드는 것입니다.WebClient 른다로ReactorClientHttpConnector
// for REST API 1 with sslContext1
WebClient webClient1 = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(
HttpClient.create()
.secure(sslContextSpec -> sslContextSpec.sslContext(sslContext1))
))
.build();
// for REST API 1 with sslContext2
WebClient webClient2 = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(
HttpClient.create()
.secure(sslContextSpec -> sslContextSpec.sslContext(sslContext2))
))
.build();
그리고 우리는 끝!
또한 이러한 클라이언트는 기본적으로 이벤트 루프 그룹을 공유하는 것이 좋습니다.그러나 다음을 사용하여 구성하면 그렇지 않습니다.runOn 는또를사여하를 하여 사용합니다.ReactorResourceFactory리소스에 대한 자세한 내용은 https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-client-builder-reactor-resources 에서 확인할 수 있습니다.
언급URL : https://stackoverflow.com/questions/45418523/spring-5-webclient-using-ssl
'source' 카테고리의 다른 글
| 도커 파일을 통해 도커 이미지를 구축하는 동안 cmd 라인을 통해 ENV 변수를 전달할 수 있습니까? (0) | 2023.08.13 |
|---|---|
| VBA와 Net을 사용한 Excel 자동화의 장단점 (0) | 2023.08.13 |
| Angular2에서 문자열 값을 구성 요소에 전달하는 방법 (0) | 2023.08.13 |
| tnsnames.ora 파일이 없는 Oracle 연결 문자열 (0) | 2023.08.13 |
| Angular Event Emitter Error: 0개의 유형 인수가 필요하지만 1개를 받았습니다. (0) | 2023.08.13 |