Java 11 SSL 异常:找不到所请求目标的有效证书路径



在尝试将我的一个应用程序从java 8升级到java 11的过程中,我遇到了一个奇怪的SSL异常,关于"找不到有效的认证">

此应用程序的配置会使用包中的cacerts覆盖默认ca-certificates-javaJDK/JREcacerts,因此在升级之前和之后,密钥存储中的证书应相同(这也使用keytools进行验证):

# java 8
ls -l /usr/lib/jvm/java-1.8.0/jre/lib/security/cacerts
lrwxrwxrwx 1 root root 41 Sep 11 22:52 /usr/lib/jvm/java-1.8.0/jre/lib/security/cacerts -> /etc/pki/java/cacerts
# java 11
ls -l /usr/lib/jvm/jdk-11.0.2/lib/security/cacerts
lrwxrwxrwx 1 root root 21 Oct 29 21:22 /usr/lib/jvm/jdk-11.0.2/lib/security/cacerts -> /etc/pki/java/cacerts

调查了几天,但我没有得到任何结果。我认为这可能是由于版本1.811.0之间的SunJSSE安全Provider的变化引起的,但我无法确认。

我不熟悉 java 安全性,想寻求帮助。该示例已简化为该项目,有关重现此问题的说明在 README.md

异常调用堆栈:

io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:472)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:278)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1408)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:930)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:682)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:617)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:534)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:906)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:320)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:263)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:258)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:641)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:460)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:360)
at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:443)
at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1061)
at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1048)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask.run(SSLEngineImpl.java:995)
at io.netty.handler.ssl.SslHandler.runAllDelegatedTasks(SslHandler.java:1502)
at io.netty.handler.ssl.SslHandler.runDelegatedTasks(SslHandler.java:1516)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1400)
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1227)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1274)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:502)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:441)
... 17 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 java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:385)
at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:290)
at java.base/sun.security.validator.Validator.validate(Validator.java:264)
at java.base/sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:313)
at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:276)
at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:141)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:619)
... 32 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297)
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380)
... 38 more

注意: 该项目是用netty建立的,SSL上下文是使用nettySslContext建立的。我也尝试使用javax.net.ssl.SSLContext

SSLEngine engine = SSLContext.getDefault().createSSLEngine();
engine.setUseClientMode(true);

这会导致相同的异常和调用堆栈。

我用 Java 调试运行了您的 docker 映像 (-Djavax.net.debug=all) 并找到了以下内容。 此 Github 问题可能会帮助您找到解决方案。

javax.net.ssl|DEBUG|0F|nioEventLoopGroup-2-1|2019-11-06 06:13:01.316 UTC|CertificateMessage.java:357|Consuming server Certificate handshake message (
"Certificates": [
"certificate" : {
"version"            : "v3",
"serial number"      : "00 90 76 89 18 E9 33 93 A0",
"signature algorithm": "SHA256withRSA",
"issuer"             : "CN=invalid2.invalid, OU="No SNI provided; please fix your client."",
"not before"         : "2015-01-01 24:00:00.000 UTC",
"not  after"         : "2030-01-01 24:00:00.000 UTC",
"subject"            : "CN=invalid2.invalid, OU="No SNI provided; please fix your client."",
"subject public key" : "RSA",
"extensions"         : [
{

如果我记得的话,我们在从 JAVA11 迁移到 JAVA8 时遇到了类似的问题,作为将/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.172-9.b11.fc28.x86_64/jre/lib/security/cacerts的内容复制到$JAVA_HOME/jre/lib/security/cacerts解决问题的解决方法。

最新更新