使用 jersey 客户端通过 HTTPS 调用 api 时出现错误 handshake_failure。我已关闭服务器证书有效性检查
Posted
技术标签:
【中文标题】使用 jersey 客户端通过 HTTPS 调用 api 时出现错误 handshake_failure。我已关闭服务器证书有效性检查【英文标题】:I am getting the error handshake_failure when using jersey client to call api with HTTPS. I have turned off the server certificate validity check 【发布时间】:2016-09-15 11:13:12 【问题描述】:我在使用 jersey 客户端通过 HTTPS 调用 api 时收到 error handshake_failure。 如果该站点以 HTTP 托管,那么它工作正常。 我在使用 HTTPS 时也关闭了服务器证书有效性检查。
@Test
public void GetMember2()
try
System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");
Date today1 = new Date(); // default window is 1 hour
String stringToday1 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US).format(today1);
Client client = Client.create(configureClient());
WebResource webResource = client.resource("https://test.abcd.net/Members/72771583886/promotions?startDate=12122015");
ClientResponse response = webResource.accept("application/xml")
.type("application/xml")
.header("Date", stringToday1)
.get(ClientResponse.class);
if (response.getStatus() != 200)
throw new RuntimeException("Failed : HTTP error code : "
+ response.getStatus());
String output = response.getEntity(String.class);
System.out.println("Output from Server .... \n");
System.out.println(output);
catch (Exception e)
e.printStackTrace();
public static ClientConfig configureClient()
TrustManager[ ] certs = new TrustManager[ ]
new X509TrustManager()
public X509Certificate[] getAcceptedIssuers()
return null;
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException
;
SSLContext ctx = null;
try
ctx = SSLContext.getInstance("TLS");
ctx.init(null, certs, new SecureRandom());
catch (java.security.GeneralSecurityException ex)
HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());
ClientConfig config = new DefaultClientConfig();
try
config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties(
new HostnameVerifier()
public boolean verify(String hostname, SSLSession session)
return true;
,
ctx
));
catch(Exception e)
return config;
错误:com.sun.jersey.api.client.ClientHandlerException: javax.net.ssl.SSLHandshakeException:收到致命警报: 握手失败在 com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:155) 在 com.sun.jersey.api.client.Client.handle(Client.java:652) 在 com.sun.jersey.api.client.WebResource.handle(WebResource.java:682) 在 com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74) 在 com.sun.jersey.api.client.WebResource$Builder.get(WebResource.java:509) 在 Frameworks.Prototype2.GetLoyaltyMember2(Prototype2.java:106) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(未知来源)在 java.lang.reflect.Method.invoke(未知来源)
【问题讨论】:
当我使用 HTTPS 连接调用 api 时,以下代码在 C#/Visual Studio 中完美运行。我无法在 Java 中找到类似的东西。 //关闭服务器证书有效性检查 ServicePointManager.ServerCertificateValidationCallback = delegate(object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) return true; ; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 |安全协议类型.Tls11 |安全协议类型.Tls; 您也可以从较旧的 JDK 版本中获取此错误(可能来自 JDK 中包含的不同/较旧的 TLS 支持)。例如,使用 1.7 执行的相同代码会出现此错误,但 1.8 不会。 【参考方案1】:暂时打开 Java 网络库的调试以查看您遇到的 SSL 错误类型:-Djavax.net.debug=all
【讨论】:
【参考方案2】:握手可能因各种原因而失败,而不仅仅是证书验证问题。 它可能用于:
不共享相同的密码套件 不共享 SSL 版本 证书验证 打算更改 TLS 版本 其他找出问题所在的最佳方法是安装 Wireshark 并查看握手消息。然后根据从服务器发送到客户端的 SSL 警报消息,您可以获得有关 SSL 握手失败的更多信息,具体发生在哪里。
此链接也可能有帮助:Received fatal alert: handshake_failure through SSLHandshakeException
【讨论】:
当我使用 HTTPS 连接调用 api 时,以下代码在 C#/Visual Studio 中完美运行。我无法在 Java 中找到类似的东西。 //关闭服务器证书有效性检查 ServicePointManager.ServerCertificateValidationCallback = delegate(object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) return true; ; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11; @user6332513,好的,只需使用wireshark或其他工具了解为什么会出现SSL警报。它是什么警报类型。【参考方案3】:从oracle网站下载jce_policy-8.zip并解压得到以下2个JAR-files。
local_policy.jar US_export_policy.jar
在您的 JVM 中更新上述 2 个策略,即在我的情况下为 /Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/jre/lib/security
它应该可以工作。
【讨论】:
以上是关于使用 jersey 客户端通过 HTTPS 调用 api 时出现错误 handshake_failure。我已关闭服务器证书有效性检查的主要内容,如果未能解决你的问题,请参考以下文章
Jersey jax.rs 客户端 2.5 遵循从 HTTP 到 HTTPS 的重定向
带有 Jersey 客户端版本 2.2 的 Restful WebService 调用
使用ClientResponse发布时,Jersey客户端MessageBodyProviderNotFoundException