我试图用Java代码从安全(即SSL)网页中读取.我正在尝试使用URLConnection(java.net)和Apache的HTTPClient.在这两种情况下,当我发出请求时,我得到以下异常:
javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX路径验证失败:java.security.cert.CertPathValidatorException:基本约束检查失败:pathLenConstraint侵犯 - 这个证书必须在证书路径中的最后证书在COM com.sun.net上的com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1518)上的.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:150) .ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:174)at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:168)at com.sun.net.ssl.internal .ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:848)at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:106)at com.sun.net.ssl.internal.ssl.Handshaker .processLoop(Handshaker.java:495)在com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433)在com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl .java:818)在com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1030)在com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1057)在com.sun.net.ssl.在sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:402)sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(在sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)的sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:934)上的AbstractDelegateHttpsURLConnection.java:166) com.sap.river.coghead.rest.Main.main(Main.java:32)中的.sap.river.coghead.rest.Main.testJavaHTTPConnection(Main.java:45)引起:sun.security.validator.ValidatorException :PKIX路径验证失败:java.security.cert.CertPathValidatorException:基本约束检查失败:违反了pathLenConstraint - 此证书必须是ce中的最后一个证书 sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:187)的sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:139)at sun.security.validator.Validator.validate(Validator.java)的rtification path :203)at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:172)at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(SSLContextImpl.java:320)at java.security.cert.CertPathValidatorException:com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:841)... 13多个所致基本约束检查失败:pathLenConstraint侵犯 - 这个证书必须是位于sun.security的sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:139)sun.security.provider.certpath.PKIXCertPathValidator.doValidate(PKIXCertPathValidator.java:316)的证书路径中的最后一个证书. provider.certpath.PKIXCertPathValidator.engineValidate(PK IXCertPathValidator.java:178)在java.security.cert.CertPathValidator.validate(CertPathValidator.java:206)在sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:182)... 18多个
请注意,我已成功建立非ssl连接,但不同的主机.我也可以使用浏览器查看此页面 - 证书在那里正确验证.
您是否需要以某种方式更改证书的顺序,因为它们是从服务器检索的?我缺少一些配置吗?
提前致谢,
利奥尔
我进一步深入研究,答案在于我需要将必要的证书导入JVM使用的密钥库来验证SSL.密钥库是jre中用于运行程序的jre/lib/security文件夹下的"cacerts"文件.
我手动导出了网站的证书 - 所有这些证书.
然后我使用Sun提供的'keytool'实用程序将其导入我的默认密钥库.请注意,您必须以正确的顺序导入它们.
然后我把新的密钥库而不是JRE的密钥库 - 它起作用了.
我想将证书直接导入JRE的密钥库会更好,但该工具要求我提供一个我不知道的密码.
我相信还有一种方法可以更轻松地编程,但还没有找到它.我很乐意得到一些指针(JSSE中的TrustManager类?).
最后,有些功劳.这篇文章:http://javaishdiscoveries.blogspot.com/2009/02/battle-with-cacerts-and-https.html帮助我指出了正确的方向.