【问题标题】:Spring Cloud Gateway: javax.net.ssl.SSLHandshakeException: No available authentication schemeSpring Cloud Gateway:javax.net.ssl.SSLHandshakeException:没有可用的身份验证方案
【发布时间】:2020-10-18 11:15:36
【问题描述】:

我正在尝试配置从 Web 浏览器到 Spring Cloud Gateway 的 TLS 连接,但出现以下异常:

2020-10-18 12:46:49.119  WARN 7652 --- [ctor-http-nio-5] .s.ApplicationProtocolNegotiationHandler : [id: 0x6fa1f964, L:/0:0:0:0:0:0:0:1:443 - R:/0:0:0:0:0:0:0:1:50229] Failed to select the application-level protocol:

javax.net.ssl.SSLHandshakeException: No available authentication scheme
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131) ~[na:na]
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117) ~[na:na]
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:313) ~[na:na]
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:269) ~[na:na]
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:260) ~[na:na]
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateProducer.onProduceCertificate(CertificateMessage.java:955) ~[na:na]
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateProducer.produce(CertificateMessage.java:944) ~[na:na]
    at java.base/sun.security.ssl.SSLHandshake.produce(SSLHandshake.java:436) ~[na:na]
    at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.goServerHello(ClientHello.java:1234) ~[na:na]
    at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.consume(ClientHello.java:1170) ~[na:na]
    at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.onClientHello(ClientHello.java:852) ~[na:na]
    at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.consume(ClientHello.java:813) ~[na:na]
    at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392) ~[na:na]
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:444) ~[na:na]
    at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1061) ~[na:na]
    at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1048) ~[na:na]
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:770) ~[na:na]
    at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask.run(SSLEngineImpl.java:995) ~[na:na]
    at io.netty.handler.ssl.SslHandler.runAllDelegatedTasks(SslHandler.java:1550) ~[netty-handler-4.1.52.Final.jar:4.1.52.Final]
    at io.netty.handler.ssl.SslHandler.runDelegatedTasks(SslHandler.java:1564) ~[netty-handler-4.1.52.Final.jar:4.1.52.Final]
    at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1448) ~[netty-handler-4.1.52.Final.jar:4.1.52.Final]
    at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1275) ~[netty-handler-4.1.52.Final.jar:4.1.52.Final]
    at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1322) ~[netty-handler-4.1.52.Final.jar:4.1.52.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:501) ~[netty-codec-4.1.52.Final.jar:4.1.52.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:440) ~[netty-codec-4.1.52.Final.jar:4.1.52.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) ~[netty-codec-4.1.52.Final.jar:4.1.52.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.52.Final.jar:4.1.52.Final]
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.52.Final.jar:4.1.52.Final]
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.52.Final.jar:4.1.52.Final]
    at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]

我了解到,当您使用 JDK 11 并且证书使用 DSA 算法时,可能会发生此错误。但就我而言,CA 和服务器证书是使用 RSA 2048 位和 X.509 格式生成的,并使用以下 keytool 命令导入密钥库:

$ keytool -import -trustcacerts -alias root -file certs/foo_com.ca-bundle -keystore keystore.p12 -storepass 123456
$ keytool -import -trustcacerts -alias tomcat -file certs/foo_com.crt -keystore keystore.p12 -storepass 123456

application.yml

server:
  forward-headers-strategy: framework
  ssl:
    enabled: true
    key-alias: tomcat
    key-store-password: 123456
    key-store: classpath:keystore.p12
    key-store-type: PKCS12
    trust-store: classpath:keystore.p12
    trust-store-password: 123456
    trust-store-type: PKCS12
  port: 443
  http2:
    enabled: true

我想要从浏览器到网关的 TLS,但从网关到微服务保持一个普通的 http 请求。所以我没有在微服务中配置任何密钥库,但也许这也是必要的?

【问题讨论】:

    标签: java spring ssl spring-cloud-gateway


    【解决方案1】:

    需要明确的是,此异常可能是由使用 WITH TLS1.3 的 DSA 证书(和密钥)引起的。 Java 11 up 实现了 TLS1.3,(向后移植的)8u261 也是如此。但是,11 和 8 包括 8u261 到 10,支持较低的协议 TLS 1.0-1.2,它确实允许基于 DSA 的密码套件——如果客户端(也)支持并提供它们,现在比以前更罕见了,但可能取决于您使用的特定浏览器。

    但是,任何 SSL/TLS 服务器总是需要带有 PRIVATEKEY 的证书,并且通常带有适用的链或中间证书以及可选的根证书。您提供了显然是服务器证书和名为“bundle”的文件,您显然认为该文件是或包含根。一个名为“bundle”的文件通常有多个证书,尽管不一定,而且您不会显示任何数据来确定其中的内容,以及它是否实际上是或包含根。 SSL/TLS 实际上并不需要根,尽管 Java 鼓励您包含它,因为 Java 加密用于 SSL/TLS 之外的其他事物,并且某些其他事物可能需要根。 keytool -importcert-import 是缩写)在创建新的(trustedCert)条目时实际上不会处理捆绑包,它只需要第一个证书并忽略任何其他证书。 (这与导入到现有 privateKey 条目的情况不同。)您没有提供私钥,也没有说明您是否拥有它,因此此“密钥库”不能用于 SSL /TLS 服务器。 (Java 对实际包含私钥的密钥库和实际上仅包含证书而不包含私钥的信任库使用相同的“密钥库”文件格式和内部 API。对于服务器,您需要前者。)

    由于您根本没有提供任何描述“CA 和服务器证书是如何生成的”,因此不可能就您应该做什么提供任何有用的建议,除了您必须提供私钥和证书的通用建议Java 可以使用的一种形式,即密钥库。注意 PKCS12 不是 Java 支持的唯一类型的密钥库,尽管它是最具互操作性的,并且对于 Java 9 是默认值,因此通常更可取。

    对于出站连接(您的应用程序是客户端),只有在您使用客户端身份验证时,您才需要一个密钥库(可能与服务器的单独或组合),又名客户端证书,这不是 SSL/TLS 中的默认值。这个选择是由服务器控制的——这里是“微服务”——如果(且仅当)他们使用 SSL/TLS,所以你需要找出或测试那些你想用。将 TLS 与客户端身份验证、没有客户端身份验证的 TLS 或没有 TLS 一起使用是否可取、合适甚至必要,取决于您 Q 中没有的许多因素,并且可能已经决定,因此可能不是您的选择。但这绝不会影响您(“网关”)从浏览器接收和接受的连接。

    【讨论】:

    • 错误是我只导入了没有私钥的crt。我创建了一个 .p12 并导入到密钥库中,一切都像魅力一样工作。
    猜你喜欢
    • 2019-09-15
    • 2021-04-28
    • 2022-01-11
    • 2018-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多