我需要设置一个支持SSL的Apache HTTPASyncClient。我使用了下面的代码,但它似乎不起作用(获取"javax.net.ssl.SSLException:收到致命警报:握手失败")
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");
}
});
4条答案
按热度按时间pxy2qtax1#
(我最近(在Android上)遇到了非常类似的问题,但我猜你也犯了和我一样的错误。)
显式设置连接管理器时:
builder.setConnectionManager(cm)
sslContext被忽略。您可以做的是将SSL上下文注入到PoolingNHttpClientConnectionManager中。
为此,可以使用此构造函数:池化NHttpClient连接管理器(组织、Apache、http、nio、reactor、连接IOReact器、注册表IO会话工厂注册表)
iosessionFactoryRegistry包含使用您的SSL上下文构建的SSLIOSessionStrategy
ej83mcc02#
下面是一个工作示例:
vyswwuz23#
我的异步模式示例:
dw1jzc5e4#
这里有很多很好的答案,但是在写这个答案的时候,我在httpcomponents库中找到了很多方便的构建器,例如,为了创建一个基于信任的sslcontext,我使用了以下方法: