问题现象 前些天第三方公司同我们公司开发的业务系统对接,调用我们系统的https接口时出现如下日志提示:javax。net。ssl。SSLHandshakeException:sun。security。validator。ValidatorException:PKIXpathbuildingfailed:sun。security。provider。certpath。SunCertPathBuilderException:unabletofindvalidcertificationpathtorequestedtarget 问题分析 几经周折,历经磨难后发现,此类问题一般是证书本身或者jdk版本问题导致的。解决问题的办法也有几种。 第一种办法:重新申请更换符合安全规范的证书。(推荐) 第二种办法:重写SSLSocketFactory类,信任所有所有证书。publicclassHttpsClientUtil{privatestaticThreadSafeClientConnManagercmnull;多连接的线程安全的管理器privatestaticintMAXTOTAL500;最大连接数privatestaticintdefaultMaxConnection100;默认最大主机连接数publicfinalstaticintCONNECTTIMEOUT10000;连接超时时间publicfinalstaticintSOCKETTIMEOUT90000;读取数据超时时间static{设置访问协议SchemeRegistryschemeRegistrynewSchemeRegistry();schemeRegistry。register(newScheme(http,80,PlainSocketFactory。getSocketFactory()));try{schemeRegistry。register(newScheme(https,443,getSSLSocketFactory()));}catch(KeyManagementExceptione1){e1。printStackTrace();}catch(NoSuchAlgorithmExceptione1){e1。printStackTrace();}cmnewThreadSafeClientConnManager(schemeRegistry);try{cm。setMaxTotal(MAXTOTAL);每条通道的并发连接数设置(连接池)cm。setDefaultMaxPerRoute(defaultMaxConnection);}catch(NumberFormatExceptione){e。printStackTrace();}}publicstaticHttpClientgetHttpsClient(){HttpParamsparamsnewBasicHttpParams();HTTP协议的版本,1。11。00。9params。setParameter(CoreProtocolPNames。PROTOCOLVERSION,HttpVersion。HTTP11);连接超时HttpConnectionParams。setConnectionTimeout(params,CONNECTTIMEOUT);请求超时HttpConnectionParams。setSoTimeout(params,SOCKETTIMEOUT);returnnewDefaultHttpClient(cm,params);}设置信任所有证书returnthrowsKeyManagementExceptionthrowsNoSuchAlgorithmExceptionprivatestaticSSLSocketFactorygetSSLSocketFactory()throwsKeyManagementException,NoSuchAlgorithmException{SSLContextctxSSLContext。getInstance(SSL);SSLContextctxSSLContext。getInstance(TLS);X509TrustManagertmnewX509TrustManager(){publicvoidcheckClientTrusted(X509Certificate〔〕xcs,Stringstring)throwsCertificateException{}publicvoidcheckServerTrusted(X509Certificate〔〕xcs,Stringstring)throwsCertificateException{}publicX509Certificate〔〕getAcceptedIssuers(){returnnull;}};ctx。init(null,newTrustManager〔〕{tm},null);SSLSocketFactoryssfnewSSLSocketFactory(ctx,SSLSocketFactory。ALLOWALLHOSTNAMEVERIFIER);信任所有域名主机returnssf;}publicstaticvoidrelease(){if(cm!null){cm。shutdown();}}} 第三种办法:把安全证书导入到java中cacerts证书库。 废话不多说,直接上干货。第一步是要下载证书 建议使用谷歌浏览器,如下图所示,点击小锁。 证书下载 在证书页面,点击复制到文件按钮,选择https证书存放到的目录位置。 复制证书到文件 在证书导出向导页面,选择base64编码。 选择编码导入证书 切换到jdkjre的libsecurity下,执行如下命令:keytoolimportaliastestkeystorecacertsfileD:test。cer 说明: alias指定别名 keystore指定存储文件 file指定证书文件所在的目录 注意:当切换到cacerts文件所在的目录时,才可指定keystorecacerts,否则应该指定全路径。此时命令行会提示你输入cacerts证书库的密码,敲入changeit即可,这是java中cacerts证书库的默认密码。 库密钥口令输入:changeit 是否信任:y 证书导入成功。查看证书,密钥默认是changeitkeytoollistkeystorecacertsaliastest更新证书时,要先删除原来的证书,然后导入新的证书keytoollistkeystorecacertskeytooldeletealiastestkeystorecacertskeytoolimportaliastestfilemytest。cerkeystorecacertstrustcacerts