1、问题描述
项目上最近有个需求,要调用外部的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
2、分析
由于是https的接口,且接口可以直接从浏览器访问返回结果,这里又报SSLHandshakeException,所以基本就是安全证书的问题,网上搜了一下,发现有很多解决方法,但是我处理的过程中还是出了一些问题的。
3、解决方法
1)安装证书
此步骤主要是参考一下博客
解决 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX 路径构建失败-CSDN博客
安装完之后,重新启动服务
又报如下错误
javax.net.ssl.SSLPeerUnverifiedException: Hostname 10.10.10.102 not verified:
certificate: sha256/zoKl5fu2gFTYZppA156ZYvBYqiaiYqZ0bp+9x/0p3Lg=
DN: CN=WIN-7NT90JF9U1S
subjectAltNames: []
这个错误表明你的Java应用程序尝试访问一个使用HTTPS协议的接口时,SSL证书验证未通过。错误的关键部分是 "SSLPeerUnverifiedException: Hostname 10.10.10.102 not verified",这表示主机名验证失败。
你的请求的目标主机名是 "10.10.10.102",但 SSL 证书中的主题(Subject)或主题备用名称subjectAltNames(Subject Alternative Names)中没有包含这个主机名。
2)处理主机名问题
处理主机名问题,主要有下面三种方法
1.使用域名而不是IP地址: 如果可能的话,使用服务器的域名而不是 IP 地址来访问 HTTPS 接口。
2.更新SSL证书: 确保服务器上的SSL证书包含了正确的主机名。你可能需要更新服务器上的证书或者向证书颁发机构申请包含正确主机名的证书。
3.忽略主机名验证(不推荐): 在开发或测试阶段,你可以选择忽略主机名验证。但在生产环境中,强烈建议进行正确的主机名验证,以确保安全性。
由于项目上访问的是别人直接提供的接口,且并没有提供接口的校验,只要网络通,就可以直接调用;并且没有域名;所以我用了忽略主机名的第三种方案。
OkHttpClient client = new OkHttpClient.Builder()
.hostnameVerifier(new AllowAllHostnameVerifier())
.build();
主要就是添加了 new AllowAllHostnameVerifier() 允许所有hostname 通过验证,然后再打包部署,调用成功。