根本原因是lettuce未显式调用usessl()启用ssl握手,且ssl连接需强制指定protocolversion.resp2并配置正确truststore与hostnameverifier;spring.redis.ssl=true不会自动触发ssl启用。

Spring Boot 3.x 连接 Redis 启用 SSL 后出现 SSLHandshakeException: General SSLEngine problem,根本原因几乎总是证书信任链未就位或主机名验证失败——不是配错端口,也不是密码错误。
Redis SSL 连接必须显式启用 useSsl(),否则走明文协议
哪怕你配置了 spring.redis.ssl=true、用了 rediss:// 协议、甚至把证书放对了位置,LettuceConnectionFactory 默认仍不启用 SSL 握手。Lettuce 的连接构建器必须手动调用 useSsl() 才会加载 SslConnectionProvider。
- Spring Boot 3.x 的
spring-boot-starter-data-redis不会自动为你调用useSsl(),哪怕spring.redis.ssl=true已设 - 必须通过
LettuceClientConfigurationBuilderCustomizer注入自定义逻辑 - 错误写法:
clientOptions.builder().build()—— 缺少.useSsl(),等同于没开 SSL - 正确写法:
clientOptions.builder().useSsl().build()
禁用主机名验证需绕过 Lettuce 默认的 DefaultHostnameVerifier
Lettuce 在 SSL 握手后默认校验服务端证书的 Subject Alternative Name (SAN) 或 CN 是否匹配你连接的 host。自签名证书或内网域名(如 redis-cluster.internal)必然失败,报错类似 java.security.cert.CertificateException: No subject alternative names matching IP address 10.0.2.15 found。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 不能靠配置项关闭,必须代码级替换
HostnameVerifier - 使用
new NoopHostnameVerifier()(注意是 Apache HttpComponents 的,不是 JDK 自带的) - 需搭配
sslOptions()显式传入自定义SSLSocketFactory和HostnameVerifier - 若混用 Bouncy Castle 或旧版
javax.net.ssl类,可能触发ClassCastException
证书格式与 TrustStore 必须匹配 JDK 17+ 默认策略
Spring Boot 3.x 基于 JDK 17+,其 trustStore 默认只信任 CA 签发证书,且拒绝 TLSv1.1 及以下协议、弱密钥交换算法。自签名证书必须导入到 JVM truststore,不能只靠配置 spring.redis.ssl.trust-store(该配置仅对部分老客户端有效,Lettuce 忽略它)。
- 别再用
keytool -import -file ca.crt -keystore $JAVA_HOME/jre/lib/security/cacerts—— JDK 17+ 的cacerts路径已变,且修改系统 truststore 风险高 - 推荐做法:生成独立
truststore.jks,用keytool -importcert导入你的 CA 或自签证书,再在启动时加 JVM 参数:-Djavax.net.ssl.trustStore=/path/to/truststore.jks -Djavax.net.ssl.trustStorePassword=changeit - 务必确认
enabled-protocols包含TLSv1.2或TLSv1.3,JDK 17+ 默认禁用 TLSv1 -
spring.redis.ssl.trust-store-type设为JKS或PKCS12均可,但类型必须与你生成的文件一致
Lettuce 6.4.x 存在 RESP3 协议握手缺陷,强制降级到 RESP2 是刚需
Spring Boot 3.4 默认拉取 Lettuce 6.4.1,该版本在启用 SSL 时与 Redis 7.x 的 HELLO 命令协商失败,表现为连接卡住、超时或抛出 Cannot decode command,底层实际是 SSL 握手成功但协议协商崩溃。
- 不升级 Lettuce 到 6.5+ 的前提下,必须显式指定
ProtocolVersion.RESP2 - 配置方式:在
LettuceClientConfigurationBuilderCustomizer中设置clientOptions.builder().protocolVersion(ProtocolVersion.RESP2).useSsl()... - 若跳过这步,即使证书、端口、密码全对,也会在连接池初始化阶段静默失败
- 验证是否生效:debug 时检查
LettuceConnectionFactory.getClusterClientOptions().getClientOptions().getProtocolVersion()是否为RESP2
真正容易被忽略的是:SSL 握手失败时,Lettuce 日志默认不打印详细 TLS 握手过程(除非开启 io.lettuce.core.protocol DEBUG 级别),你看到的 SSLHandshakeException 往往只是表象;背后可能是证书过期、OCSP 响应超时、SNI 扩展缺失、甚至国产信创环境下的国密套件不兼容——这些都需要从 JVM 层抓包或启用 -Djavax.net.debug=ssl:handshake 才能定位。










