Java 在浏览器中工作的RestTemplate GET请求中握手失败
我无法向第三方https URL发送简单GET请求,该URL在浏览器中运行良好:Java 在浏览器中工作的RestTemplate GET请求中握手失败,java,java-8,httpclient,resttemplate,handshake,Java,Java 8,Httpclient,Resttemplate,Handshake,我无法向第三方https URL发送简单GET请求,该URL在浏览器中运行良好: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://...": Received fatal alert: handshake_failure; nested exception is javax.net.ssl.SSLHandshakeException: Received fa
org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://...": Received fatal alert: handshake_failure; nested exception is javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:673)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:635)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:556)
我试着跟随,但没有找到解决办法
没有证书,我正在使用Java 8,尝试添加-djse.enableSNIExtension=false-Dhttps.protocols=TLSv1.2、TLSv1.1、TLSv1等解决方案
添加了与浏览器发送相同的标题(Accept
和User-Agent
),但没有运气
代码
还尝试使用具有相同输出的配置:
TrustStrategy acceptingTrustStrategy=(X509Certificate[]链,字符串authType)->true
SSLContext SSLContext=org.apache.http.ssl.SSLContexts.custom()
.loadTrustMaterial(空,acceptingTrustStrategy)
.build()
或同时与:
可关闭的httpClient httpClient
=HttpClients.custom()
.setSSLHostnameVerifier(新的NoopHostnameVerifier())
.build();
HttpComponents客户端HttpRequestFactory请求工厂
=新的HttpComponents客户端HttpRequestFactory();
setHttpClient(httpClient)
curl-v结果服务器证书:
* subject: CN=*.site.com,OU=Domain Control Validated
* start date: May 24 08:13:23 2019 GMT
* expire date: May 24 08:13:23 2021 GMT
* common name: *.site.com
* issuer: CN=Go Daddy Secure Certificate Authority - G2,OU=http://certs.godaddy.com/repository/,O="GoDaddy.com, Inc.",L=Scottsdale,ST=Arizona,C=US
编辑
我将证书添加到java中,如下所示:
证书已添加到密钥库
我看到证书是在浏览器中加载的,它在JMeter中工作,但在使用restTemplate或ApacheHttpClient时仍然失败,并出现相同的错误
我正在使用Java8更新151
尝试从@rmunge answer添加BouncyCastleProvider,但仍然存在相同的错误
根本原因很可能是缺少对最新的基于EC的密码套件的支持,如TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
椭圆曲线加密(ECC)由SunEC
提供商实现。要充分发挥功能,需要以下各项:
- SunEC必须在中国上市 jre/lib/security/java.security和jdk.tls.disabledAlgorithms的值不能包含ECDHE
- 本机库libsunce.so/ sunce.dll必须位于jre/lib(Linux、Mac)或jre/bin(Windows)文件夹中
- 确保JDK JCE框架使用无限策略。自Java 8u161以来 这是新的默认设置,对于旧版本,您可能必须安装JCE Unlimited Strength辖区策略文件和/或在java.security文件中进行更改。有关更多说明,请参阅
另一种选择是使用第三方加密提供商,如Bouncy Castle,它有自己的ECC提供商。有关说明,请参见问题及其公认的答案。您能否指定您正在使用的Java版本!!!如果是Java 7,那么这将为您完成任务 我可以看到你的客户解析为TLSv1。从
openssl
输出您的服务器不支持TLSv1
尽管JavaSE7版本中的SunJSSE支持TLS1.1和TLS
1.2,默认情况下,这两个版本均未为客户端连接启用。某些服务器无法正确实现前向兼容性,并且
拒绝与TLS 1.1或TLS 1.2客户交谈。对于互操作性,
默认情况下,SunJSSE不为客户端启用TLS 1.1或TLS 1.2
联系
通过以下任一方式启用TLSv1.1和TLSv1.2:
-Dhttps.protocols=TLSv1.2,TLSv1.1,TLSv1
System.setProperty("https.protocols", "TLSv1.2,TLSv1.1,TLSv1");
注意:选项1和2中的协议顺序从好到坏(TLS版本1.2到1)更改。您可以使用cURL或类似工具执行请求吗?可能您的浏览器的信任存储区与Java或类似的东西不同。@Smutje curl通过启用完整的urlIs证书检查来工作?@Nish默认restTemplate为
new restTemplate()
时也会发生这种情况,我相信@Smutje是正确的。也许您的java信任存储没有服务器CA证书,您可以尝试将其添加到您的java信任存储,这将是我的第一次尝试。确实,我忽略了不可用的密码套件:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,在ssl logI中无法执行jrunscript-e'exit(javax.crypto.cipher.getMaxAllowedKeyLength(“RC5”)) >= 256);' || 如果[$?-等式1];然后回显“JCE已安装”;else回显“JCE未安装或错误”;fi
错误$?此时出现意外情况。
和libsunec.so在openjdk github项目中找不到文件javax.crypto.Cipher.getMaxAllowedKeyLength(“RC5”)>=256
返回错误openjdk github项目仅包含相应的源代码:例如,openjdk版本包含libsunec.so文件。我从adoptopenjdk.net下载的64位linux版本包含jre/lib/amd64中的文件您有什么确切的java版本?
sudo keytool -importcert -file filename.cer -alias randomaliasname -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit
security.provider.6=org.bouncycastle.jce.provider.BouncyCastleProvider
-Dhttps.protocols=TLSv1.2,TLSv1.1,TLSv1
System.setProperty("https.protocols", "TLSv1.2,TLSv1.1,TLSv1");