mysql 8.0中require子句不支持指定tls版本,仅控制是否启用加密连接;真正决定tls版本的是服务端tls_version变量和客户端能力,需通过show status like 'ssl_version'验证实际协商结果。

MySQL 8.0中REQUIRE子句不支持直接指定TLS版本号
MySQL的REQUIRE子句(如CREATE USER ... REQUIRE SSL或REQUIRE X509)**无法指定TLS协议版本**,它只控制“是否启用加密连接”,不参与TLS握手协商过程。真正决定TLS版本的是服务端配置的tls_version系统变量和客户端实际支持的协议能力,REQUIRE对此无约束力。
常见误解是以为写REQUIRE TLSv1.2就能生效——这在MySQL语法中根本不存在,会报错ERROR 1064 (42000)。MySQL从不把TLS版本作为用户级权限条件。
-
REQUIRE SSL:仅强制该用户必须走加密通道,但用TLSv1.2还是TLSv1.3,由服务端tls_version和客户端能力共同决定 -
REQUIRE X509:进一步要求客户端提供有效证书,仍不干预TLS协议选择 - 即使用户设了
REQUIRE SSL,若服务端tls_version只配了TLSv1.3,而客户端只支持TLSv1.2,连接仍会失败(报SSL connection error: protocol version mismatch)
真正控制TLS版本的地方只有两个:服务端tls_version和客户端显式声明
服务端统一控制入口:在my.cnf的[mysqld]段设置tls_version=TLSv1.2,TLSv1.3(注意逗号无空格),MySQL 8.0.16+才支持该配置项;低于此版本只能靠OpenSSL底层限制,不可控。
客户端必须主动配合,否则默认走明文:
- 命令行工具:
mysql --ssl-mode=REQUIRED是底线,不加这个参数,哪怕服务端开了TLS,连接仍是明文 - Java应用:JDBC URL需加
?useSSL=true&requireSSL=true&enabledTLSProtocols=TLSv1.2,且JDK版本要匹配(Java 8u161+才默认启用TLSv1.2) - Python(PyMySQL):必须传
ssl={'ca': '/path/to/ca.pem'},否则ssl_disabled=False无效 - 旧客户端(如MySQL 5.7默认编译版)可能因缺失SSL库直接报
SSL connection error,不是配置问题,是二进制本身不带加密能力
require_secure_transport=ON后,REQUIRE子句的实际作用被弱化
当服务端设了require_secure_transport=ON,所有TCP/IP连接都必须加密,此时REQUIRE SSL对用户已无额外约束力——它变成全局策略的冗余表达。但仍有两点例外:
- Unix socket或Windows shared memory连接不受
require_secure_transport限制,此时REQUIRE SSL仍可阻止该用户走本地非加密通道 - 如果服务端未开
require_secure_transport,而你只想让某个高敏用户强制加密,则REQUIRE SSL是唯一手段 - 注意:
REQUIRE不校验证书有效性,要防中间人,必须配合--ssl-ca或JDBC的trustCertificateKeyStoreUrl等客户端侧证书验证机制
验证当前连接实际使用的TLS版本
连上后执行SHOW STATUS LIKE 'Ssl_version';,返回值才是真实协商结果,比如TLSv1.2或TLSv1.3。别信配置文件写了什么,得看这个。
容易忽略的点:MySQL 8.0.28+已彻底移除TLSv1.0/TLSv1.1支持,哪怕tls_version里写了也无效;而客户端若硬编码只发TLSv1.1的ClientHello,服务端直接断连,不会降级——这种兼容性断裂必须提前在客户端日志里捕获(用-Djavax.net.debug=ssl:handshake)。











