@xtccc
2017-05-17T08:39:45.000000Z
字数 1710
阅读 2290
Java
在通过scalaj访问NREL的API时,某天突然报错:
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(Unknown Source)
at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
at sun.security.validator.Validator.validate(Unknown Source)
经查,是因为运行这段代码的jdk的jre/lib/security/cacerts
跟别的正常机器的文件有些不一样,替换过来就好了。
本地测试:
下载文件 SSLPoke.class
然后执行:
$ java SSLPoke developer.nrel.gov 443
如果返回如下就说明正常了:
$ java SSLPoke developer.nrel.gov 443
Successfully connected
参考: Unable to Connect to SSL Services due to PKIX Path Building Failed
如果我们允许Java程序访问非安全的网站,则即使没有证书,也不会报异常:
val resp: HttpResponse[String] = WithException {
Http(url)
.option(HttpOptions.connTimeout(60000))
.option(HttpOptions.readTimeout(60000))
// must set this, otherwise will see exception:
// sun.security.validator.ValidatorException:
// PKIX path building failed:
// sun.security.provider.certpath.SunCertPathBuilderException:
// unable to find valid certification path to requested target
.option(HttpOptions.allowUnsafeSSL)
.asString
}.asInstanceOf[HttpResponse[String]]
val body: String = resp.body
实际上本质原因是我们的Java app通过HTTPS链接无法识别被访问网站的root certificate authentication (CA)。
如果要求Java程序必须以安全的形式来访问网站,则必须将目标网站的证书提供给Java程序。
参考 这里
用Chrome打开目标网站:https://developer.nrel.gov/
打开 View -> Developer -> Developer Tools,然后点击Security可以看到:
然后点击 View certificate,就能看到三级证书:
下面把证书导出来(首先安装工具gnutls-bin):
$ gnutls-cli --print-cert developer.nrel.gov < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > developer.nrel.gov.cert
好了,可以看到本地生成了一个证书文件developer.nrel.gov.cert。