背景:
系统调用外部Https接口,外部接口提供方更换了网站证书,导致我们(https客户端)报错
堆栈信息如下(抹去了业务代码的堆栈)
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) ~[?:1.8.0_45]
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1937) ~[?:1.8.0_45]
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302) ~[?:1.8.0_45]
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296) ~[?:1.8.0_45]
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1478) ~[?:1.8.0_45]
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:212) ~[?:1.8.0_45]
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979) ~[?:1.8.0_45]
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914) ~[?:1.8.0_45]
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1050) ~[?:1.8.0_45]
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363) ~[?:1.8.0_45]
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391) ~[?:1.8.0_45]
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1375) ~[?:1.8.0_45]
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:394) ~[httpclient-4.5.2.jar!/:4.5.2]
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:353) ~[httpclient-4.5.2.jar!/:4.5.2]
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:141) ~[httpclient-4.5.2.jar!/:4.5.2]
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353) ~[httpclient-4.5.2.jar!/:4.5.2]
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380) ~[httpclient-4.5.2.jar!/:4.5.2]
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236) ~[httpclient-4.5.2.jar!/:4.5.2]
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184) ~[httpclient-4.5.2.jar!/:4.5.2]
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88) ~[httpclient-4.5.2.jar!/:4.5.2]
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) ~[httpclient-4.5.2.jar!/:4.5.2]
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184) ~[httpclient-4.5.2.jar!/:4.5.2]
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) ~[httpclient-4.5.2.jar!/:4.5.2]
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107) ~[httpclient-4.5.2.jar!/:4.5.2]
//省去业务代码堆栈
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-4.3.12.RELEASE.jar!/:4.3.12.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738) ~[spring-aop-4.3.12.RELEASE.jar!/:4.3.12.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.3.12.RELEASE.jar!/:4.3.12.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) ~[spring-tx-4.3.12.RELEASE.jar!/:4.3.12.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282) ~[spring-tx-4.3.12.RELEASE.jar!/:4.3.12.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.3.12.RELEASE.jar!/:4.3.12.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.12.RELEASE.jar!/:4.3.12.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-4.3.12.RELEASE.jar!/:4.3.12.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.12.RELEASE.jar!/:4.3.12.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673) ~[spring-aop-4.3.12.RELEASE.jar!/:4.3.12.RELEASE]
at com.sankuai.zc.open.inform.service.impl.TradeOrderStatusHTTPInformServiceImpl$$EnhancerBySpringCGLIB$$f64e4cff.inform2Biz(<generated>) ~[open-inform-0.0.1-SNAPSHOT.jar!/:0.0.1-SNAPSHOT]
at com.sankuai.zc.open.inform.service.dispatcher.InformDispatcherService.inform(InformDispatcherService.java:58) ~[open-inform-0.0.1-SNAPSHOT.jar!/:0.0.1-SNAPSHOT]
at com.sankuai.zc.open.inform.service.mqService.DelayMqListener.callback(DelayMqListener.java:103) ~[open-inform-0.0.1-SNAPSHOT.jar!/:0.0.1-SNAPSHOT]
at com.sankuai.zc.open.inform.notify.InformAbstractService.doDelayMqCallBack(InformAbstractService.java:53) ~[open-inform-0.0.1-SNAPSHOT.jar!/:0.0.1-SNAPSHOT]
at com.sankuai.zc.open.inform.service.mqService.DelayMqListener.lambda$recvMessage$7(DelayMqListener.java:84) ~[open-inform-0.0.1-SNAPSHOT.jar!/:0.0.1-SNAPSHOT]
at com.sankuai.zc.open.inform.service.mqService.DelayMqListener$$Lambda$50/106665305.run(Unknown Source) ~[?:?]
at com.meituan.mtrace.thread.TraceRunnable.run(TraceRunnable.java:30) ~[mtrace-agent-1.1.24.1.jar!/:?]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_45]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_45]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[?:1.8.0_45]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[?:1.8.0_45]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-all-4.1.31.Final.jar!/:4.1.31.Final]
at java.lang.Thread.run(Thread.java:745) ~[?:1.8.0_45]
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) ~[?:1.8.0_45]
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292) ~[?:1.8.0_45]
at sun.security.validator.Validator.validate(Validator.java:260) ~[?:1.8.0_45]
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324) ~[?:1.8.0_45]
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229) ~[?:1.8.0_45]
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124) ~[?:1.8.0_45]
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1460) ~[?:1.8.0_45]
... 46 more
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:145) ~[?:1.8.0_45]
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131) ~[?:1.8.0_45]
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280) ~[?:1.8.0_45]
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382) ~[?:1.8.0_45]
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292) ~[?:1.8.0_45]
at sun.security.validator.Validator.validate(Validator.java:260) ~[?:1.8.0_45]
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324) ~[?:1.8.0_45]
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229) ~[?:1.8.0_45]
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124) ~[?:1.8.0_45]
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1460) ~[?:1.8.0_45]
... 46 more
首先curl -v分别在自己本地和服务端上访问该域名,都返回ok,说明不是证书问题。与SRE开会沟通,SRE提起说之前处理过类似的问题,原因是因为jdk8的版本过低,升级jdk8的子版本,问题解决,
总结:unable to find valid certification path to requested target一般是如下原因导致
1.服务器证书过新,jdk识别不了:比如新增的加密算法、不同的证书格式等,会直接阻塞。 需要升级jdk
2.服务器证书过旧,jdk识别不了,但是jdk一般会向下兼容
3.证书内容校验失败:比如无可信的根证书、证书已过期等。但通常都可以不阻塞请求(提示不安全)
原因3比较好排除,curl -v测试一下或者拷贝下来网站证书在线校验一下即可
如何查看网站证书:https://blog.youkuaiyun.com/ever_peng/article/details/93720072