首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Apache HttpAsyncClient中配置SSL

在Apache HttpAsyncClient中配置SSL
EN

Stack Overflow用户
提问于 2015-02-01 13:10:00
回答 3查看 4.6K关注 0票数 7

我需要设置一个带有SSL支持的Apache HTTPAsyncClient。我使用这段代码,但它似乎不起作用(获得"javax.net.ssl.SSLException:接收到致命警报: handshake_failure")

代码语言:javascript
复制
    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答案,我最终使用以下代码运行它

代码语言:javascript
复制
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");                
    }
});    
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-02-01 13:34:47

(我最近遇到了非常类似的问题(在Android上),但我想您正在犯与我相同的错误。)

当您显式地设置连接管理器:builder.setConnectionManager(cm)时,sslContext将被忽略。

您可以做的是将SSLContext注入到PoolingNHttpClientConnectionManager中。

为此,可以使用以下构造函数:PoolingNHttpClientConnectionManager(org.apache.http.nio.reactor.ConnectingIOReactor感应器,注册表iosessionFactoryRegistry)

在iosessionFactoryRegistry中使用SSLContext包含SSLIOSessionStrategy构建

票数 5
EN

Stack Overflow用户

发布于 2017-07-24 08:57:43

下面是一个有用的例子:

代码语言:javascript
复制
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;
}
票数 1
EN

Stack Overflow用户

发布于 2018-03-20 12:21:39

我在异步模式下的示例:

代码语言:javascript
复制
     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;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28263055

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档