我需要设置一个带有SSL支持的Apache HTTPAsyncClient。我使用这段代码,但它似乎不起作用(获得"javax.net.ssl.SSLException:接收到致命警报: handshake_failure")
System.setProperty("javax.net.debug", "ssl,handshake");
System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true");
KeyStore ts = KeyStore.getInstance("JKS");
ts.load(loadStream("C:/TrustStore/cacerts"), "trustpass".toCharArray());
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(loadStream("C:/KeyStore/SSL/keystore.SomeKey"), "keypass".toCharArray());
SSLContextBuilder sslBuilder = SSLContexts.custom().loadTrustMaterial(ts).loadKeyMaterial(ks, "somekey".toCharArray()).setSecureRandom(new SecureRandom());
SSLContext ssl = sslBuilder.build();
PoolingNHttpClientConnectionManager cm = new PoolingNHttpClientConnectionManager(new DefaultConnectingIOReactor(IOReactorConfig.DEFAULT));
CloseableHttpAsyncClient clientHttps = HttpAsyncClientBuilder.create()
.setConnectionManager(cm)
.setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
.setSSLContext(ssl)
.build();
RequestConfig.Builder b = RequestConfig.custom();
b.setProxy(new HttpHost("proxyHost", proxyPort));
RequestConfig rc = b.build();
clientHttps.start();
HttpRequestBase req = new HttpPost("https://someurl");
((HttpEntityEnclosingRequestBase)req).setEntity(new StringEntity("somestring"));
req.setConfig(rc);
clientHttps.execute(req, new FutureCallback<HttpResponse>() {
@Override
public void failed(Exception ex) {
System.out.println(ex);
}
@Override
public void completed(HttpResponse result) {
System.out.println(result);
}
@Override
public void cancelled() {
System.out.println("Cancelled");
}
}); 当使用javax.net.ssl.HttpsURLConnection实现这一点时,它可以工作(如果需要的话,我可以附加相关代码)。
编辑
基于@ben75答案,我最终使用以下代码运行它
System.setProperty("javax.net.debug", "ssl,handshake");
System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true");
KeyStore ts = KeyStore.getInstance("JKS");
ts.load(loadStream("C:/TrustStore/cacerts"), "trustpass".toCharArray());
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(loadStream("C:/KeyStore/SSL/keystore.SomeKey"), "keypass".toCharArray());
SSLContextBuilder sslBuilder = SSLContexts.custom().loadTrustMaterial(ts).loadKeyMaterial(ks, "somekey".toCharArray()).setSecureRandom(new SecureRandom());
SSLContext ssl = sslBuilder.build();
SSLIOSessionStrategy s = new SSLIOSessionStrategy(ssl, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
RegistryBuilder<SchemeIOSessionStrategy> rb = RegistryBuilder.create();
rb.register("https", s).register("http", NoopIOSessionStrategy.INSTANCE);
PoolingNHttpClientConnectionManager cm = new PoolingNHttpClientConnectionManager(new DefaultConnectingIOReactor(IOReactorConfig.DEFAULT), rb.build());
CloseableHttpAsyncClient clientHttps = HttpAsyncClientBuilder.create()
.setConnectionManager(cm)
.build();
RequestConfig.Builder b = RequestConfig.custom();
b.setProxy(new HttpHost("proxyHost", proxyPort));
RequestConfig rc = b.build();
clientHttps.start();
HttpRequestBase req = new HttpPost("https://someurl");
((HttpEntityEnclosingRequestBase)req).setEntity(new StringEntity("somestring"));
req.setConfig(rc);
clientHttps.execute(req, new FutureCallback<HttpResponse>() {
@Override
public void failed(Exception ex) {
System.out.println(ex);
}
@Override
public void completed(HttpResponse result) {
System.out.println(result);
}
@Override
public void cancelled() {
System.out.println("Cancelled");
}
}); 发布于 2015-02-01 13:34:47
(我最近遇到了非常类似的问题(在Android上),但我想您正在犯与我相同的错误。)
当您显式地设置连接管理器:builder.setConnectionManager(cm)时,sslContext将被忽略。
您可以做的是将SSLContext注入到PoolingNHttpClientConnectionManager中。
为此,可以使用以下构造函数:PoolingNHttpClientConnectionManager(org.apache.http.nio.reactor.ConnectingIOReactor感应器,注册表iosessionFactoryRegistry)
在iosessionFactoryRegistry中使用SSLContext包含SSLIOSessionStrategy构建
发布于 2017-07-24 08:57:43
下面是一个有用的例子:
public SSLContext getSSLContext() {
final TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
try {
final SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom()
.loadTrustMaterial(null, acceptingTrustStrategy)
.build();
sslContext.getServerSessionContext().setSessionCacheSize(1000);
return sslContext;
} catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {
}
return null;
}
public Registry<SchemeIOSessionStrategy> getSSLRegistryAsync() {
return RegistryBuilder.<SchemeIOSessionStrategy>create()
.register("http", NoopIOSessionStrategy.INSTANCE)
.register("https", new SSLIOSessionStrategy(
getSSLContext(), null, null, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)).build();
}
public PoolingNHttpClientConnectionManager getPoolingNHttpClientConnectionManager() {
try {
final PoolingNHttpClientConnectionManager connectionManager =
new PoolingNHttpClientConnectionManager(new DefaultConnectingIOReactor(IOReactorConfig.DEFAULT), getSSLRegistryAsync());
connectionManager.setMaxTotal(connectionPoolMax);
connectionManager.setDefaultMaxPerRoute(connectionPoolMaxPerRoute);
return connectionManager;
} catch (IOReactorException e) {
}
return null;
}
public RequestConfig getRequestConfig() {
return RequestConfig.custom()
.setConnectTimeout(connectTimeout)
.setSocketTimeout(socketTimeout)
.setConnectionRequestTimeout(socketTimeout)
.setCookieSpec(CookieSpecs.IGNORE_COOKIES)
.build();
}
public CloseableHttpAsyncClient getHttpAsyncClient() {
final CloseableHttpAsyncClient httpAsyncClient = HttpAsyncClients.custom()
.setConnectionManager(getPoolingNHttpClientConnectionManager())
.setDefaultRequestConfig(getRequestConfig())
.build();
return httpAsyncClient;
}发布于 2018-03-20 12:21:39
我在异步模式下的示例:
try {
SSLContext sslContext = getSSLContext(X509Cert);
CloseableHttpAsyncClient httpAsyncClient = getHttpAsyncClient(sslContext,HTTP_CLIENT_MAX_POOL_CONNECTIONS,HTTP_CLIENT_MAX_PER_ROUTE_CONN);
setHttpAsyncClient(httpAsyncClient);
} catch (Exception e) {
LOG.error("Generic SSL Error Adapter: {} - {}", e.getMessage(), e.getLocalizedMessage());
}
}
private SSLContext getSSLContext(X509CertificateValidator trustStrategy) {
try {
final SSLContext sslContext = SSLContexts.custom()
.loadTrustMaterial(null, trustStrategy)
.build();
sslContext.getServerSessionContext().setSessionCacheSize(1000);
return sslContext;
} catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {
LOG.error("SSL Context creation error: {} - {}", e.getMessage(), e.getLocalizedMessage());
}
return null;
}
private Registry<SchemeIOSessionStrategy> getSSLRegistryAsync(SSLContext sslContext) {
Registry<SchemeIOSessionStrategy> defaultRegistry = RegistryBuilder.<SchemeIOSessionStrategy> create()
.register("http", NoopIOSessionStrategy.INSTANCE)
.register("https", new SSLIOSessionStrategy(sslContext, NoopHostnameVerifier.INSTANCE))
.build();
return defaultRegistry;
}
private PoolingNHttpClientConnectionManager getPoolingNHttpClientConnectionManager(SSLContext sslContext, int connectionPoolMax, int connectionPoolMaxPerRoute) {
try {
PoolingNHttpClientConnectionManager connectionManager =
new PoolingNHttpClientConnectionManager(new DefaultConnectingIOReactor(IOReactorConfig.DEFAULT), getSSLRegistryAsync(sslContext));
connectionManager.setMaxTotal(connectionPoolMax);
connectionManager.setDefaultMaxPerRoute(connectionPoolMaxPerRoute);
return connectionManager;
} catch (IOReactorException e) {
LOG.error("NHttp Connectio Manager error: {} - {}", e.getMessage(), e.getLocalizedMessage());
}
return null;
}
public CloseableHttpAsyncClient getHttpAsyncClient(SSLContext sslContext, int connectionPoolMax, int connectionPoolMaxPerRoute) {
final CloseableHttpAsyncClient httpAsyncClient = HttpAsyncClients.custom()
.setConnectionManager(getPoolingNHttpClientConnectionManager(sslContext, connectionPoolMax, connectionPoolMaxPerRoute))
//.setSSLHostnameVerifier(new NoopHostnameVerifier())
.build();
return httpAsyncClient;
}https://stackoverflow.com/questions/28263055
复制相似问题