[英]How to create a pool of Apache HttpClients with varying SSL client auth certificates
我一直在嘗試創建一個使用 Apache HttpClient 調用各種 RESTful Web 服務的客戶端的 Apache 文檔和其他示例。 (這些 Web 服務中的每一個都可能需要不同的客戶端證書進行身份驗證)。 最初,我創建了一個靜態代碼塊,用於初始化 HttpClient(帶有 SSLContext 信息和池連接管理器):
private static CloseableHttpClient _client;
static {
HttpClientBuilder clientBuilder = HttpClients.custom();
SSLContextBuilder sslContextBuilder = SSLContexts.custom();
sslContextBuilder.loadTrustMaterial(new TrustSelfSignedStrategy());
sslContextBuilder.loadKeyMaterial(new File("clientcert.p12"), password, password, (aliases, socket) -> aliases.keySet().iterator().next());
SSLContext sslContext = sslContextBuilder.build();
HostnameVerifier allowAllHosts = new NoopHostnameVerifier();
SSLConnectionSocketFactory connectionFactory = new SSLConnectionSocketFactory(sslContext, allowAllHosts);
clientBuilder.setSSLSocketFactory(connectionFactory);
RegistryBuilder<ConnectionSocketFactory> regBuilder = RegistryBuilder.<ConnectionSocketFactory>create();
regBuilder.register("https", connectionFactory);
regBuilder.register("http", new PlainConnectionSocketFactory());
Registry<ConnectionSocketFactory> socketFactoryRegistry = regBuilder.build();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
clientBuilder.setConnectionManager(connectionManager);
_client = clientBuilder.build();
}
此時,我可以使用客戶端來執行請求,並且只要服務器配置為允許訪問 clientcert.p12,客戶端身份驗證就可以正常工作。
我需要的是能夠根據所需客戶端證書的值動態更改每個請求的客戶端證書。
是否可以在動態更改客戶端證書的同時重用靜態 HttpClient? 此外,如果這是可能的,我仍然會看到使用池連接管理器的性能優勢嗎?
有一個未http.socket-factory-registry
執行上下文屬性可以用來覆蓋連接管理器在構建時設置的連接套接字工廠。
CloseableHttpClient httpClient = HttpClientBuilder.create()
.setSSLContext(SSLContexts.createSystemDefault())
.build();
SSLContext customSSlContext = SSLContexts.custom()
.loadKeyMaterial(new File("my-keystore.jks"), "sectret".toCharArray(), "sectret".toCharArray())
.build();
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", new SSLConnectionSocketFactory(customSSlContext))
.build();
HttpClientContext clientContext = HttpClientContext.create();
clientContext.setAttribute("http.socket-factory-registry", socketFactoryRegistry);
try (CloseableHttpResponse response = httpClient.execute(new HttpGet("https://host/stuff"), clientContext)) {
System.out.println(response.getStatusLine());
EntityUtils.consume(response.getEntity());
}
使用相同的客戶端實例/相同的連接池執行具有不同用戶身份/安全上下文的多個線程的請求時,請務必謹慎使用。
我在這里發布了我使用PoolingHttpClientConnectionManager
類的解決方案,這個對我PoolingHttpClientConnectionManager
:
SSLConnectionSocketFactory sslConnectionFactory = new SSLConnectionSocketFactory(sslContext, new DefaultHostnameVerifier());
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory> create()
.register("https", sslConnectionFactory)
.register("http", new PlainConnectionSocketFactory())
.build();
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
CloseableHttpClient httpClient = HttpClients.custom()
.setSSLContext(sslContext)
.setDefaultRequestConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build())
.setConnectionManager(cm)
.build();
cm.setMaxTotal(200);
cm.setDefaultMaxPerRoute(20);
final ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient);
engine.setFollowRedirects(false);
ResteasyClient client = clientBuilder.httpEngine(engine).build();
ResteasyWebTarget target = client.target(UriBuilder.fromPath(
"https://my.server.com/mtls/protected/resource"));
String response = target.request().get(String.class);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.