https请求java证书异常SSLHandshakeException
前言
因项目对接第三方系统需要升级,起因是项目对接cfca的接口进行升级,原本想着很简单的没啥大事,当我做完后,部署在测试环境,一切都是那么的顺畅。但是。。。。。昨天晚上投产在生产时,就出现java证书异常,当时本地测试和在测试环境上是没问题的,离了个大谱…
报错信息
日志如下(示例):
Caused by: cfca.etl.common.client.exception.ClientException: 通信异常
at cfca.etl.common.client.Client.processException(Client.java:250)
at cfca.etl.uaclient.UAClient.process(UAClient.java:137)
at com.daokoujinke.system.live.LiveBaseService.ocrNew(LiveBaseService.java:269)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282)
at org.springframework.cloud.context.scope.GenericScope$LockedScopedProxyFactoryBean.invoke(GenericScope.java:485)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698)
at com.daokoujinke.system.live.LiveBaseService$$EnhancerBySpringCGLIB$$cefda786.ocrNew(<generated>)
at com.daokoujinke.system.live.LiveBodyService.ocrNew(LiveBodyService.java:257)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282)
at org.springframework.cloud.context.scope.GenericScope$LockedScopedProxyFactoryBean.invoke(GenericScope.java:485)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
... 78 common frames omitted
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153)
at cfca.etl.common.client.connector.HttpConnector.connect(HttpConnector.java:184)
at cfca.etl.common.client.connector.HttpConnector.sendAndReceive(HttpConnector.java:83)
at cfca.etl.common.client.Client.sendAndReceive(Client.java:160)
at cfca.etl.uaclient.UAClient.process(UAClient.java:117)
... 98 common frames omitted
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1491)
... 112 common frames omitted
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:146)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
... 118 common frames omitted
处理过程
1.检查配置
看到这个问题的瞬间,我们就把第三方提供的证书啥的在环境上和配置上检查了一遍,没发现有什么问题,那就怀疑是网络问题。
2.排查网络
使用命令telnet是通的,头开始大了,,,怀疑是不是网络策略配置代理导致的,项目生产包放到测试环境,和本地测试生产的配置,发现都是可以的,这更加证实了我的猜想,就让运维去联系服务器运营商去排产网络策略,心想这回应该没问题的了吧,最后排除了一个多小时运维得出结论是网络没啥问题。这tm的就难受了,没办法继续看呗,在网上查阅很多资料,发现有类似的报错,发现是证书原因,于是就按照网上的教程来处理。
3.证书原因
3.1查看当前已经加入的java信任的证书
keytool -list -keystore /usr/java/jdk1.8.0_65/jre/lib/security/cacerts
3.2下载cer证书
从浏览器中导出证书,并上传到服务器。IE,火狐点击地址栏中的 锁 右边箭头->更多信息->查看证书->详细信息->导出。格式是DER二进制编码(X.509).cer和base64的我都下了, 将证书传到服务器。
3.3Linux下 cer证书导入
3.3.1 首先是切换到这个目录下面
${JAVA_HOME}/jre/lib/security
3.3.2 然后导入证书
如下
keytool -import -alias wecloud -keystore cacerts -file ${JAVA_HOME}/jre/lib/security/wecloud.cer
例子
keytool -import -alias wx -keystore /data/java/jdk1.8.0_65/jre/lib/security/cacerts -file /data/java/jdk1.8.0_65/jre/lib/security/wx.cer
/usr/local/jdk1.7/jre/lib/security/zhengshu.cer,
其中/usr/local/jdk1.7为环境jdk位置,/usr/local/jdk1.7/jre/lib/security/zhengshu.cer
为我上传的第三步从浏览器中导出的证书上传至服务器的路径,回车后要输入密码,密码默认为changeit
其中${JAVA_HOME}/jre/lib/security/wecloud.cer 为证书所在位置,alias 后面是证书别名,如需输入秘钥口令:
秘钥口令:changeit
3.3.3 查看证书是否导入成功
查看命令:
keytool -list -keystore ${java_home}/jre/lib/security/cacerts
${java_home}/是javahome的路径。
3.3.4 重启服务
做完后,让运维重启系统。以为万事大吉了,最后还是报错了,心态彻底崩了,把版本回退,把问题甩锅给第三方。。。。。。。。。。。。。
实战
keytool -import -alias wx -keystore /data/java/jdk1.8.0_65/jre/lib/security/cacerts -file /data/java/jdk1.8.0_65/jre/lib/security/wx.cer -storepass changeit
keytool -list -keystore /data/java/jdk1.8.0_65/jre/lib/security/cacerts
#进入jdk目录
cd /data/java/jdk1.8.0_65/jre/lib/security
#查看证书
keytool -list -keystore cacerts -storepass changeit
keytool -list -keystore /data/java/jdk1.8.0_65/jre/lib/security/cacerts -storepass changeit
#导出
keytool -keystore <keystore file> -alias <alias> -export -file <certfilename>.cert
#导入
keytool -keystore <truststore file> -alias <alias> -import -file <certfilename>.cert
4.最终处理方案
晚上回家的时候这个问题一直在小编的脑海,毕竟甩锅不是小编的风格。回想每一步处理的过程,突然想起是不是jdk版本的原因呢,因为本地和测试都是可以的,于是查询本地和测试服务器上的java版本,命令:
java -version
本地版本:
C:\Users\Administrator>java -version
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)
测试服务器上的版本:
[root@cs-104 ~]# java -version
java version "1.8.0_201"
Java(TM) SE Runtime Environment (build 1.8.0_201-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)
生产上的版本:
[zjsk@zhjrfy-02 ~]$ java -version
java version "1.8.0_65"
Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode)
于是第二天一早,赶紧让运维把生产的jdk换到测试上,部署生产相关的jks配置,发现同样的问题。把java版本升级又可以,到这大功告成了,不容易呀。
总结
今天主要是总结这次投产出现的问题及解决问题的过程,一个版本引发的bug,让我受益良多。好了,小编先行告辞!