无法在 Java 中对 SSL 站点进行身份验证:“违反了 pathLenConstraint - 此证书必须是证书路径中的最后一个证书”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/829522/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Unable to authenticate to SSL site in java: "pathLenConstraint violated - this cert must be the last cert in the certification path"
提问by Lior
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:
我正在尝试从安全(即 SSL)网页中读取 Java 代码。我正在尝试同时使用 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
. 13 更多 引起:java.security.cert.CertPathValidatorException:基本约束检查失败:违反 pathLenConstraint - 此证书必须是 sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:139) 认证路径中的最后一个证书) 在 sun.security.provider.certpath.PKIXCertPathValidator.doValidate(PKIXCertPathValidator.java:316) 在 sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:178) 在 java.security.cert.CertPathValidator.validate( CertPathValidator.java:206) 在 sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:182) ... 18 更多 . 13 更多 引起:java.security.cert.CertPathValidatorException:基本约束检查失败:违反 pathLenConstraint - 此证书必须是 sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:139) 认证路径中的最后一个证书) 在 sun.security.provider.certpath.PKIXCertPathValidator.doValidate(PKIXCertPathValidator.java:316) 在 sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:178) 在 java.security.cert.CertPathValidator.validate( CertPathValidator.java:206) 在 sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:182) ... 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
利奥尔
回答by Lior
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.htmlhelped to point me in the right direction.
最后,一些信用。这篇文章在这里:http: //javaishdiscoveries.blogspot.com/2009/02/battle-with-cacerts-and-https.html帮助我指明了正确的方向。
回答by dr_bonzo
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?
这是一个很好的解决方案吗?任何意见?
回答by dr_bonzo
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
我还没有亲自修复证书。但这篇文章很有帮助