在 JAVA API 上使用时让我们加密证书不起作用

Posted

技术标签:

【中文标题】在 JAVA API 上使用时让我们加密证书不起作用【英文标题】:Let's Encrypt Certificate not working while using on JAVA API 【发布时间】:2019-06-12 20:06:38 【问题描述】:

我正在开发一个通过 HTTP 提供 REST API 的 Java 应用程序。

出于安全原因,此通信应切换到 HTTPS。

我使用 certbot 工具从 Let's Encrypt 生成了一个受信任的证书,当我从 Chrome 浏览器调用我的 API 时,该证书似乎正在工作,但是当我使用基于 Spring RestTemplate 的 Java 1.8.0_191 客户端时出现此异常:

Exception in thread "main" 
org.springframework.web.client.ResourceAccessException: I/O error on GET 
request for "https://hostname/api/v1/event": 
sun.security.validator.ValidatorException: PKIX path building failed: 
sun.security.provider.certpath.SunCertPathBuilderException: unable to find 
valid certification path to requested target; nested exception is 
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
at 
org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:743)
at 
org.springframework.web.client.RestTemplate.execute(RestTemplate.java:669)
at 
org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:578)
at 
com.swingws.wiser.tasks.GetFrimwareVersionTask.main(GetFrimwareVersionTask.
java:80)
Caused by: 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
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1946)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:316)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:310)
at 
sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:
1639)
at 
sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:223)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1037)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:965)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1064)
at 
sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:
1367)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1395)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1379)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
at 
sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(
AbstractD
elegateHttpsURLConnection.java:185)
at 
sun.net.www.protocol.https.HttpsURLConnectionImpl.connect
(HttpsURLConnectionImpl.java:162)
at 
org.springframework.http.client.SimpleBufferingClientHttpRequest.
executeInternal(SimpleBufferingClientHttpRequest.java:76)
at 
org.springframework.http.client.AbstractBufferingClientHttpRequest
.executeIntern
al(AbstractBufferingClientHttpRequest.java:48)
at org.springframework.http.client.AbstractClientHttpRequest.
execute(AbstractClient    HttpRequest.java:53)
at 
org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:734)
... 3 more
Caused by: sun.security.validator.ValidatorException: PKIX path building 
failed: sun.security.provider.certpath.SunCertPathBuilderException: unable 
to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:397)
at 
sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:302)
at sun.security.validator.Validator.validate(Validator.java:262)
at 
sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:
324)
at 
sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java
:229)
at 
sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(
X509TrustManagerImpl.java:124)
at sun.security.ssl.ClientHandshaker.serverCertificate(
ClientHandshaker.java:1621)
... 17 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: 
unable to find valid certification path to requested target
at 
sun.security.provider.certpath.SunCertPathBuilder.build(
SunCertPathBuilder.java:141)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild( 
SunCertPathBuilder.java:126)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:392)
... 23 more

有没有办法在不将此证书添加到 Java 客户端密钥库的情况下使其正常工作?

【问题讨论】:

您是否将此证书添加到 java 信任库? 不,因为我有一个可信证书,所以不需要将它添加到我的 java 可信存储中 确实 191 版应该支持letsencrypt 证书。 能否请您使用 -Djavax.net.debug=true 运行您的客户端并显示输出? 有一个想法,不推荐用于生产代码,但如果你只是想测试一些东西,你可以随时使用-Dtrust_all_cert=true 【参考方案1】:

我们遇到了同样的问题,在我们的案例中,我们联系的服务器配置错误。它没有提供完整的证书链。您可以使用this tool 进行检查。

当服务器在您的控制之下时,您应该能够配置它。使用 Apache 时,您可以使用 SSLCertificateChainFile 进行配置。另见this answer

【讨论】:

以上是关于在 JAVA API 上使用时让我们加密证书不起作用的主要内容,如果未能解决你的问题,请参考以下文章

iOS使用openSSL加密应该怎么做

让我们加密证书、Python 和 Windows

kafka使用ssl加密和认证

提供到没有 ssl 证书的网站的加密连接

基础篇:java.security框架之签名加密摘要及证书

Java加密技术——数字证书