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 |