java - 为什么 Java 在最新的 JDK 更新后无法连接到 MySQL 5.7,应该如何解决? (ssl.SSLHandshakeException : No appropriate protocol)

标签 java mysql tls1.2

在 2021 年 4 月对 JDK 的最新更新 (11.0.11+9-0ubuntu2~18.04) 中支持 TLSv1TLSv1.1被删除,大概是因为自 2021 年 3 月起不再支持这些版本。 java.security 中的差异很明显。文件:
前:

jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, \
    EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
    include jdk.disabled.namedCurves
后:
jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \
    DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
    include jdk.disabled.namedCurves
此 SO 帖子中也对此进行了讨论:SSLHandShakeException No Appropriate Protocol .在该线程中,自更新 JDK 版本以来的最后几天也弹出了更多答案。
JDK更新后,我们收到错误
java.sql.SQLException: An attempt by a client to checkout a Connection has timed out.
c3p0 .
切换到hikari后我们得到了一个更有意义的错误:
ERROR [2021-04-29 16:21:16,426] com.zaxxer.hikari.pool.HikariPool: HikariPool-1 - Exception during pool initialization.
! javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
我们在 MySQL 5.7.33-0ubuntu0.18.04.1 上运行.现在根据我的理解,如 here 所述, MySQL 5.7 支持 TLSv1.2。同样在运行 SHOW VARIABLES LIKE 'tls_version'; 时我们得到 TLSv1,TLSv1.1,TLSv1.2这表明 TLSv1.2支持。
那么问题来了,为什么 JDK 和 MySQL 不同意使用 TLSv1.2以及我们能做些什么,让他们与 TLSv1.2 通信?
注意:我不认为更改 java.security其他线程中建议的文件是解决此问题的一个很好的长期解决方案!

最佳答案

正如@skelwa 已经评论的那样,您需要添加 enabledTLSProtocols=TLSv1.2连接字符串中的配置属性来解决您的问题。
Connector/J 的完整连接字符串可能看起来像这样:

jdbc:mysql://<host>:<port>/<dbname>?enabledTLSProtocols=TLSv1.2
对于r2dbc您需要使用 tlsVersion=TLSv1.2反而。
对于 连接器/J v8.0.28 enabledTLSProtocols更名为 tlsVersions (见 note)。但是,原始名称仍保留为别名。

剩下的问题是:
为什么 JDK 和 MySQL 不同意使用 TLSv1.2 ?
尽管双方确实都支持 TLSv1.2,但您遇到的问题是由 Connector/J 的默认行为引起的。出于兼容性原因,Connector/J 默认不启用 TLSv1.2 及更高版本。因此,必须明确启用它。
见下文note :

For Connector/J 8.0.18 and earlier when connecting to MySQL Community Server 5.6 and 5.7 using the JDBC API: Due to compatibility issues with MySQL Server compiled with yaSSL, Connector/J does not enable connections with TLSv1.2 and higher by default. When connecting to servers that restrict connections to use those higher TLS versions, enable them explicitly by setting the Connector/J connection property enabledTLSProtocols (e.g., set enabledTLSProtocols=TLSv1,TLSv1.1,TLSv1.2).



警告:请注意建议编辑 jdk.tls.disabledAlgorithms 的解决方案jre/lib/security 内部摆姿势安全风险到您的应用程序并更改其中的任何内容可能会产生严重影响!
这些协议(protocol)被禁用是有原因的,人们不应该简单地从该列表中删除所有内容,甚至只是部分内容。

注:如果您想从 JDK 获得更多低级洞察来调试您的问题,您可以通过将以下配置传递给 java 命令来启用 ssl 调试日志:-Djavax.net.debug=ssl,handshake甚至-Djavax.net.debug=all在您的情况下,您将看到如下内容:
...(HANDSHAKE_FAILURE): Couldn't kickstart handshaking (
"throwable" : {
  javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
    at java.base/sun.security.ssl.HandshakeContext.<init>(HandshakeContext.java:170)
    at java.base/sun.security.ssl.ClientHandshakeContext.<init>(ClientHandshakeContext.java:98)
    ...

关于java - 为什么 Java 在最新的 JDK 更新后无法连接到 MySQL 5.7,应该如何解决? (ssl.SSLHandshakeException : No appropriate protocol),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67332909/

相关文章:

java - 如何预加载声音并简单地在Java中播放声音?

java - 在Java中单独处理进程的输出/错误,无需额外的线程

Java - 使用 RSA key 加密

PHP 下拉菜单检索结果

java - SQLite 'INSERT OR REPLACE INTO' 不正确的行为

performance - 使用 TLS/SSL 可信证书提高性能

java - ListView 中的切换监听器给出错误的结果

javascript - 将 JavaScript 中的值直接插入 MySQL 数据库

objective-c - iOS 13 TLS 问题

ssl - 带 caddy 的 HTTPS 代理