I'm trying to read from a secure (i.e. SSL) web page, in Java code. I'm trying to use both URLConnection (java.net) and Apache's HTTPClient. In both cases, when I make the request, I get this exception:
我试图用Java代码从安全(即SSL)网页上读取。我正在尝试使用URLConnection(java.net)和Apache的HTTPClient。在这两种情况下,当我发出请求时,我得到以下异常:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: basic constraints check failed: pathLenConstraint violated - this cert must be the last cert in the certification path at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:150) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1518) at com.sun.net.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) at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:818) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1030) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1057) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1041) at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:402) at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166) at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:934) at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234) at com.sap.river.coghead.rest.Main.testJavaHTTPConnection(Main.java:45) at com.sap.river.coghead.rest.Main.main(Main.java:32) Caused by: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: basic constraints check failed: pathLenConstraint violated - this cert must be the last cert in the certification path at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:187) at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:139) at sun.security.validator.Validator.validate(Validator.java: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 com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:841) ... 13 more Caused by: java.security.cert.CertPathValidatorException: basic constraints check failed: pathLenConstraint violated - this cert must be the last cert in the certification path at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:139) at sun.security.provider.certpath.PKIXCertPathValidator.doValidate(PKIXCertPathValidator.java:316) at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:178) at java.security.cert.CertPathValidator.validate(CertPathValidator.java:206) at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:182) ... 18 more
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)at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433)at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl) .java:818)在com.sun。 net.sssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1030)位于com.sun.net.ssl的com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1057)。在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 at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:841)... 13更多引起:java.security.cert.CertPathValidatorException:基本约束检查失败:违反了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)位于sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:182)的java.security.cert.CertPathValidator.validate(CertPathValidator.java:206)... 18更多
Note that I've succeeded in establishing a non-ssl connection, to a different host though. I'm also able to view this page using the browser - the certificates are validated correctly there.
请注意,我已经成功地建立了非ssl连接,但是不同的主机。我也可以使用浏览器查看此页面 - 证书在那里正确验证。
Do you I need to somehow change the order of certificates as they are retrieved from the server? Is there some configuration I'm missing?
我是否需要以某种方式更改证书的顺序,因为它们是从服务器检索的?是否有一些我缺少的配置?
Thanks in advance,
提前致谢,
Lior
3 个解决方案
#1
I dug in further and the answer lies in the fact that I needed to import the necessary certificates into the keystore used by the JVM to authenticate SSL. The key store is the 'cacerts' file under the jre/lib/security folder in the jre that is used to run the program.
我进一步挖掘,答案在于我需要将必要的证书导入JVM使用的密钥库来验证SSL。密钥存储区是jre中用于运行程序的jre / lib / security文件夹下的“cacerts”文件。
I manually exported the site's certificates - all of them.
Then I imported it into my default keystore using the 'keytool' utility provided by Sun. Note that you have to import them in the correct order.
I then put the new keystore instead of the JRE's one - and it worked.
我手动导出了网站的证书 - 所有这些证书。然后我使用Sun提供的'keytool'实用程序将其导入我的默认密钥库。请注意,您必须以正确的顺序导入它们。然后我把新的密钥库而不是JRE的密钥库 - 它起作用了。
I guess it would've been better to import the certificates directly to the JRE's keystore, but the tool asked me for a password which i didn't know.
我想将证书直接导入JRE的密钥库会更好,但该工具要求我输入一个我不知道的密码。
I believe there's also a way to program around this more easily, just haven't found it yet. I'll be happy to get some pointers (TrustManager class in JSSE?).
我相信还有一种方法可以更轻松地对此进行编程,但还没有找到它。我很乐意得到一些指针(JSSE中的TrustManager类?)。
Finally, some credit. This post here: http://javaishdiscoveries.blogspot.com/2009/02/battle-with-cacerts-and-https.html helped to point me in the right direction.
最后,一些功劳。这篇文章:http://javaishdiscoveries.blogspot.com/2009/02/battle-with-cacerts-and-https.html帮助我指明了正确的方向。
#2
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: basic constraints check failed: pathLenConstraint violated - this cert must be the last cert in the certification path at
javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX路径验证失败:java.security.cert.CertPathValidatorException:基本约束检查失败:违反了pathLenConstraint - 此证书必须是证书路径中的最后一个证书
pathLenConstraint
see (Note about certificate chains) in
请参阅(关于证书链的说明)
google says it may be problem with certificate chain order, I have just found that my cert is not in order, not fixed yet, working on it. I will update this later.
谷歌说它可能是证书链订单的问题,我刚刚发现我的证书不合规,尚未修复,正在处理它。我稍后会更新。
old post:
Have almost the same problem.
有几乎相同的问题。
Adding certificate manualy to keystore helps, but I'd prefer to do it more automatically, with my client.
将密码库手动添加到密钥库有帮助,但我更愿意使用我的客户端更自动地执行此操作。
So my solution:
我的解决方案:
I will use keystore just for this one app, and one host 1. keystore does not exist - create with some generated password 2. save password in config file 3. ask user (or dont) whether he wants to accept this certificate 4. if so - save it to keystore, and use it when needed
我将仅为这个应用程序使用密钥库,并且一个主机1.密钥库不存在 - 使用一些生成的密码创建2.在配置文件中保存密码3.询问用户(或不要)他是否要接受此证书4.如果所以 - 将它保存到密钥库,并在需要时使用它
Is this a good solution? Any comments?
这是一个好的解决方案吗?任何意见?
#3
The problem was with certificate chain order. It was: A->C->B, but should be A->B->C, once we fixed chain order the application started to work.
问题在于证书链顺序。它是:A-> C-> B,但应该是A-> B-> C,一旦我们固定链序,应用程序就开始工作了。
I havent personally fixed the certs. but this post was helpful
我没有亲自修改证书。但这篇文章很有帮助
#1
I dug in further and the answer lies in the fact that I needed to import the necessary certificates into the keystore used by the JVM to authenticate SSL. The key store is the 'cacerts' file under the jre/lib/security folder in the jre that is used to run the program.
我进一步挖掘,答案在于我需要将必要的证书导入JVM使用的密钥库来验证SSL。密钥存储区是jre中用于运行程序的jre / lib / security文件夹下的“cacerts”文件。
I manually exported the site's certificates - all of them.
Then I imported it into my default keystore using the 'keytool' utility provided by Sun. Note that you have to import them in the correct order.
I then put the new keystore instead of the JRE's one - and it worked.
我手动导出了网站的证书 - 所有这些证书。然后我使用Sun提供的'keytool'实用程序将其导入我的默认密钥库。请注意,您必须以正确的顺序导入它们。然后我把新的密钥库而不是JRE的密钥库 - 它起作用了。
I guess it would've been better to import the certificates directly to the JRE's keystore, but the tool asked me for a password which i didn't know.
我想将证书直接导入JRE的密钥库会更好,但该工具要求我输入一个我不知道的密码。
I believe there's also a way to program around this more easily, just haven't found it yet. I'll be happy to get some pointers (TrustManager class in JSSE?).
我相信还有一种方法可以更轻松地对此进行编程,但还没有找到它。我很乐意得到一些指针(JSSE中的TrustManager类?)。
Finally, some credit. This post here: http://javaishdiscoveries.blogspot.com/2009/02/battle-with-cacerts-and-https.html helped to point me in the right direction.
最后,一些功劳。这篇文章:http://javaishdiscoveries.blogspot.com/2009/02/battle-with-cacerts-and-https.html帮助我指明了正确的方向。
#2
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: basic constraints check failed: pathLenConstraint violated - this cert must be the last cert in the certification path at
javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX路径验证失败:java.security.cert.CertPathValidatorException:基本约束检查失败:违反了pathLenConstraint - 此证书必须是证书路径中的最后一个证书
pathLenConstraint
see (Note about certificate chains) in
请参阅(关于证书链的说明)
google says it may be problem with certificate chain order, I have just found that my cert is not in order, not fixed yet, working on it. I will update this later.
谷歌说它可能是证书链订单的问题,我刚刚发现我的证书不合规,尚未修复,正在处理它。我稍后会更新。
old post:
Have almost the same problem.
有几乎相同的问题。
Adding certificate manualy to keystore helps, but I'd prefer to do it more automatically, with my client.
将密码库手动添加到密钥库有帮助,但我更愿意使用我的客户端更自动地执行此操作。
So my solution:
我的解决方案:
I will use keystore just for this one app, and one host 1. keystore does not exist - create with some generated password 2. save password in config file 3. ask user (or dont) whether he wants to accept this certificate 4. if so - save it to keystore, and use it when needed
我将仅为这个应用程序使用密钥库,并且一个主机1.密钥库不存在 - 使用一些生成的密码创建2.在配置文件中保存密码3.询问用户(或不要)他是否要接受此证书4.如果所以 - 将它保存到密钥库,并在需要时使用它
Is this a good solution? Any comments?
这是一个好的解决方案吗?任何意见?
#3
The problem was with certificate chain order. It was: A->C->B, but should be A->B->C, once we fixed chain order the application started to work.
问题在于证书链顺序。它是:A-> C-> B,但应该是A-> B-> C,一旦我们固定链序,应用程序就开始工作了。
I havent personally fixed the certs. but this post was helpful
我没有亲自修改证书。但这篇文章很有帮助