简体   繁体   English

带有SSL证书的Java HTTPS连接错误

[英]Java HTTPS connection with SSL certificate Error

I'm trying to use the SSL certificate obtained with StartSSL.com on an Apache server. 我正在尝试在Apache服务器上使用通过StartSSL.com获得的SSL证书。 The connection with browser is fine, but when I try to use a Java application, I got this exeption: 与浏览器的连接很好,但是当我尝试使用Java应用程序时,我得到了这个例外:

Exception in thread "main" 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 线程“main”中的异常javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到所请求目标的有效证书路径

I don't understand what could be the problem, because with the browser, I got the SSL with green label. 我不明白可能是什么问题,因为在浏览器中,我获得了带有绿色标签的SSL。

The problem is your Java is not trusting the certificate. 问题是您的Java不信任证书。 You have to import it to your java's truststore . 您必须将其导入java的truststore

# Copy the certificate into the directory Java_home\Jre\Lib\Security
# Change your directory to Java_home\Jre\Lib\Security>
# Import the certificate to a trust store.
# Here's the import command:

keytool -import -alias ca -file somecert.cer -keystore cacerts -storepass changeit [Return]

Trust this certificate: [Yes]

changeit is default truststore password. changeit是默认的信任库密码。

For every certificate that you imported into your truststore you have to provide a new alias. 对于导入信任库的每个证书,都必须提供新别名。

The import method is a quote from Here 导入方法是Here的引用

This message is due to: 此消息是由于:

  1. Either the JRE does not have the root CA as a trusted entry in its keystore. JRE没有将根CA作为其密钥库中的受信任条目。
  2. The server is not sending a proper chain. 服务器没有发送正确的链。

But, 2 is not valid in your case since the browser is able to construct the chain and validate the certificate. 但是,2在您的情况下无效,因为浏览器能够构建链并验证证书。

Consequently you need to get the root CA and put it in the JRE keystore as a trusted entry. 因此,您需要获取根CA并将其作为受信任条目放在JRE密钥库中。 There are lots of resources that document the "how". 有很多资源记录了“如何”。 One of them is: https://access.redhat.com/documentation/en-US/Fuse_Message_Broker/5.3/html/Security_Guide/files/i379776.html 其中之一是: https//access.redhat.com/documentation/en-US/Fuse_Message_Broker/5.3/html/Security_Guide/files/i379776.html

EDIT 1: Since you want to share the java app, it would we worth the effort to get a certificate from a CA whose root is already trusted in the trust store for the Java versions that your app supports. 编辑1:由于您想要共享Java应用程序,我们将值得努力从CA获取证书,该证书的根已经在您的应用程序支持的Java版本的信任库中受信任。

As far as I understand this is related to the Java Certificate Keystore. 据我所知,这与Java证书密钥库有关。 Your certificate is not accepted by java. 您的证书不被java接受。 Here is a link how to add your certificate to Java trusted Certificates keystore: https://docs.oracle.com/javase/tutorial/security/toolsign/rstep2.html 以下是如何将证书添加到Java可信证书密钥库的链接: https//docs.oracle.com/javase/tutorial/security/toolsign/rstep2.html

There are a few questions like this already on SO (like this one: PKIX path building failed: unable to find valid certification path to requested target ). SO上已经存在类似的一些问题(如下所示: PKIX路径构建失败:无法找到所请求目标的有效证书路径 )。

The usual answer to this is that your java client doesn't have certificates needed to complete the certificate chain. 通常的答案是您的Java客户端没有完成证书链所需的证书。

If you need proper certificate validation, then you'll have to figure out where the certificate chain breaks down. 如果您需要正确的证书验证,那么您必须弄清楚证书链发生故障的位置。 If you don't (because this is a proof of concept or a dev sandbox, or whatever), then you can easily work around this by adding the certificate to the trust store you use with your client. 如果您不这样做(因为这是概念证明或开发沙箱,或其他),那么您可以通过将证书添加到您与客户端一起使用的信任库来轻松解决此问题。

Edit: 编辑:

As for why your browser accepts this, it's likely that either your browser has the certificates in the chain that you need or you've absentmindedly told your browser to trust the certificate even though it also wasn't able to validate the certificate. 至于为什么你的浏览器会接受这个,你的浏览器可能会在你需要的链中拥有证书,或者你心不在焉地告诉你的浏览器信任证书,即使它也无法验证证书。

I recomend use http-request built on apache http api. 我建议使用建立在apache http api上的http-request

import org.junit.Test;

import static org.apache.http.HttpHeaders.ACCEPT;
import static org.apache.http.HttpStatus.SC_OK;
import static org.apache.http.entity.ContentType.APPLICATION_XML;
import static org.junit.Assert.assertEquals;

public class HttpRequestSSLTest {

private final HttpRequest<?> httpRequest = HttpRequestBuilder.createGet("https://mms.nw.ru/")
        .trustAllCertificates()
        .trustAllHosts()
        .addDefaultHeader(ACCEPT, APPLICATION_XML.getMimeType())
        .build();

@Test
public final void ignoreSSLAndHostsTest() throws Exception {

    assertEquals(SC_OK, httpRequest.execute().getStatusCode());
}

} }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM