【问题标题】:SSL handshake_failure using jersey-apache-client-1.18SSL handshake_failure 使用 jersey-apache-client-1.18
【发布时间】:2015-01-29 07:07:40
【问题描述】:

我正在使用 jersey-apache-client 进行 ssl 连接。我在验证连接时遇到握手错误。下面是握手错误。

WRITE: TLSv1 Change Cipher Spec, length = 1
Finished
verify_data:  { 165, 117, 49, 237, 116, 71, 111, 175, 161, 237, 45, 30 }
WRITE: TLSv1 Handshake, length = 48
READ: TLSv1 Alert, length = 2
RECV TLSv1 ALERT:  fatal, handshake_failure
%% Invalidated:  [Session-1, TLS_DHE_RSA_WITH_AES_128_CBC_SHA]

如果我使用 jersey-client-1.13 并且我没有收到握手错误,代码可以正常工作。

SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(keyManagerFactory.getKeyManagers(), tmf.getTrustManagers(), null);
final ClientConfig config = new DefaultClientConfig();
config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties(null, ctx));
Client create = Client.create(config);    
create.resource(targetUrl).post();

由于 jersey-client.1.13 不支持代理,所以我使用了 jersey-apache-client.1.18。在下面的代码中,我使用了 DefaultApacheHttpClientConfig,添加了代理支持,使用 ApacheHttpClient 创建了客户端。

SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(keyManagerFactory.getKeyManagers(), tmf.getTrustManagers(), null);
final DefaultApacheHttpClientConfig apacheConfig = new DefaultApacheHttpClientConfig();
final Map<String, Object> properties = apacheConfig.getProperties();
properties.put(DefaultApacheHttpClientConfig.PROPERTY_PROXY_URI, "http://" + proxyHost + ":" + proxyPort);
properties.put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties(null,ctx));   
apacheConfig.getState().setProxyCredentials(AuthScope.ANY_REALM, proxyHost,   Integer.parseInt(proxyPort),proxyUser, proxyPassword);
Client create = ApacheHttpClient.create(apacheConfig);
create.resource(targetUrl).post();

我找不到解决方案。在这两种情况下,证书都很好。

注意:我也试过不带代理的jersey apache客户端,还是有错误。

有人发现出了什么问题吗?提前致谢。

【问题讨论】:

    标签: java apache rest ssl jersey-client


    【解决方案1】:

    原因是正在为 Jersey 配置 SSL 套接字工厂,但是您使用的是 Jersey Apache 连接器,因此应直接在 Apache HttpClient 上配置 SSL 套接字工厂。对于更高版本的 Jersey (2.x),这可能会为您完成,但对于 Apache 连接器和 Jersey 1.x,您需要配置它。像这样的:

    Protocol apacheProtocol = new Protocol("https", socketFactory, 443);
    HostConfiguration hostConfig = new HostConfiguration();
    hostConfig.setHost("your.hostname.org", 443, apacheProtocol);
    HttpClient httpClient = new HttpClient();
    httpClient.setHostConfiguration(hostConfig);
    ApacheHttpClientHandler handler = new ApacheHttpClientHandler(httpClient);
    Client client = new ApacheHttpClient(handler);
    

    这里的另一个问题是,如果您在 Jersey WebResource 上使用绝对 URI(设置主机名和端口),带有自定义 SSLSocketFactory 的 HostConfiguration 将被覆盖 - 并且 HttpClient 将默认使用 JVM 的 CA 证书(对于 Apache Client 3.1 是正确的)至少)。

    如果这对您有用,您可能一直在使用受 JVM cacerts 信任的证书。 实际上,这里的一个选项是使用命令行 keytool 手动将您正在使用的证书添加到 JVM cacerts 文件(尽管对于某些应用程序,这可能不是可接受的解决方案)。

    【讨论】:

      【解决方案2】:

      这个问题基本上是由于您的本地 JAVA 和 https 站点之间的密码不匹配造成的。您可能需要为您的 JVM 安装 JCE 扩展。

      使用https://www.ssllabs.com/检查你的REST API是否支持java,check this image example

      如果显示这样,您可以从http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html 下载文件。完成后,将 JRE 的 lib/security 目录下的两个 JAR(local_policy.jar、US_export_policy.jar)替换为下载包中的 JAR。

      如果没有,请提供更多详细信息,以便我们详细检查。

      在这里查看解决方案,我只是累了How to debug the ssl connection error,它对我有用,可以拯救我的一天!

      【讨论】:

        猜你喜欢
        • 2016-12-25
        • 1970-01-01
        • 2018-04-30
        • 2015-05-16
        • 1970-01-01
        • 1970-01-01
        • 2013-07-14
        • 1970-01-01
        • 2018-02-09
        相关资源
        最近更新 更多