欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

【SSL】调用HTTPS://服务遇到错误:unable to find valid certification path to requested target

发布时间:2024/9/19 编程问答 45 豆豆
生活随笔 收集整理的这篇文章主要介绍了 【SSL】调用HTTPS://服务遇到错误:unable to find valid certification path to requested target 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

前言

  • OkHttpClient

最近有个需求,需要调用一个https开头的URL服务。
服务方提供了一个demo,但,demo是调用http的服务。
网上找了一大圈,发现盖起来要这样要那样的。都不符合我的想法,试了几个也没成功。
我的想法比较简单:有没有一种方法,让我在不改动demo的前提下,让demo跑起来。
经过我仔细地回想一下,发现这个办法可行,我之前还实现过。

错误内容

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 targetat sun.security.ssl.Alerts.getSSLException(Alerts.java:192)at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1959)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:1514)at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)at sun.security.ssl.Handshaker.process_record(Handshaker.java:961)at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1072)at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.kt:379)at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.kt:337)at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:209)at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154)at sc.HttpClientUtil.postWithJsonMsg(HttpClientUtil.java:66)at sc.appPay.main(appPay.java:105) Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested targetat sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:397)at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:302)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:1496)... 26 more Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested targetat sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:392)... 32 more

题外话

对于调用HTTPS的服务,可以参考《java 安全性编程指南》。

解决思路

将HTTPS的证书添加到本地证书库中。在程序启动时,使用指定的证书库验证证书和CA。

相关知识:

  • 当访问的URL是以https://开头的话,VM将自动地激活JSSE。
  • 服务器会向客户端发送它的证书以供验证。
  • 客户端会验证证书,以确认这个服务器正式他想链接并通信的那个服务器,并且确认签发证书的CA是可信任的。
  • 环境变量javax.net.ssl.trustStore告知客户端的JSSE使用哪个证书库。证书库中有我们可以信任的证书和CA。
  • 环境变量javax.net.ssl.trustStorePassword告知客户端的JSSE证书库的密码。
  • 如果未指定证书库,则使用缺省的证书库。缺省的证书库的位置为%JRE_HOME%/lib/security/cacerts或者%JAVA_HOME%/jre/lib/security/cacerts。默认密码为changeit。

操作

  • 拿到证书。https://开头的地址的证书很容易拿到。在浏览器中打开该地址,将浏览器中显示的证书另存为就拿到了。
  • 创建证书库。参考 【SSL】java keytool工具创建自己的(localhost)(JKS)证书库。
  • 将第1步中拿到的证书导入到证书库中。参考 【SSL】java keytool工具操作java带的(JKS)证书库。
  • 在程序中引入证书库。
  • 在合适的位置添加下面这段静态代码:

    static {File jksFile = new File("localhost.jks");System.out.println("jks file : " + jksFile.getAbsolutePath());System.setProperty("javax.net.ssl.trustStore", jksFile.getAbsolutePath());System.setProperty("javax.net.ssl.trustStorePassword", "changeit");}

    对应的项目结构为:

    项目目录 ├─src │ ├─main │ │ ├─java │ │ │ └─sc │ │ └─resources │ └─test │ ├─java │ └─resources └─localhost.jks

    其它

  • 如果使用默认的证书库,则可以省略第2步。
  • 使用默认的证书库时,在win10上导入证书遇到问题。具体原因不明。
  • 总结

    以上是生活随笔为你收集整理的【SSL】调用HTTPS://服务遇到错误:unable to find valid certification path to requested target的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。