Spring云网关:javax.net.ssl.SSLHandshakeException:没有可用的身份验证方案

Spring云网关:javax.net.ssl.SSLHandshakeException:没有可用的身份验证方案,java,spring,ssl,spring-cloud-gateway,Java,Spring,Ssl,Spring Cloud Gateway,我正在尝试配置从web浏览器到Spring云网关的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 pro

我正在尝试配置从web浏览器到Spring云网关的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

服务器:
转发头策略:框架
ssl:
已启用:true
密钥别名:tomcat
密钥存储密码:123456
密钥存储:类路径:keystore.p12
密钥存储类型:PKCS12
信任存储:类路径:keystore.p12
信任存储密码:123456
信任存储类型:PKCS12
港口:443
http2:
已启用:true

我想让TLS从浏览器到网关,但从网关到微服务保留一个简单的http请求。因此,我没有在微服务中配置任何密钥库,但这可能也是必要的?

要清楚,使用TLS1.3的DSA证书(和密钥)可能会导致此异常。Java11Up实现了TLS1.3,8u261(后端口)也实现了TLS1.3。但是,11 up和8 up(包括8u261到10)都支持较低的协议TLS 1.0-1.2,如果客户机(也)支持并提供基于DSA的密码套件,则该协议允许使用基于DSA的密码套件,这一点现在比以前更加少见,但可能取决于您使用的特定浏览器

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

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


对于出站连接(您的应用程序就是客户机),只有在使用客户机身份验证(也称为客户机证书,不是SSL/TLS中的默认值)时,才需要密钥库(可能与服务器的密钥库分开或组合)。这种选择由服务器控制——这里是“微服务”——如果(并且仅当)它们使用SSL/TLS,那么您需要了解或测试您想要使用的SSL/TLS。是否需要、适当或甚至有必要使用具有客户端身份验证的TLS、不具有客户端身份验证的TLS或无TLS取决于Q中没有的许多因素,并且可能已经决定了,因此可能不是您的选择。但在任何情况下,这都不会影响您(“网关”)从浏览器接收和接受的连接。

错误在于我只导入了crt而没有私钥。我创建了一个.p12,并将其导入keystore,一切都像一个符咒。