MySQL 8.0+ 创建 REQUIRE SSL 用户连接失败,首要检查服务端是否真正启用 SSL:需确保 have_ssl=YES、ssl_ca/cert/key 路径正确且可读、SELinux/AppArmor 未拦截;其次确认 TLS 协议版本兼容(如服务端 tls_version 与客户端匹配);再核对客户端 SSL 参数(如 JDBC 须用 sslMode=REQUIRED 而非 useSSL=true);最后必须启用 require_secure_transport=ON 才能强制全局 SSL。

MySQL 8.0+ 创建 REQUIRE SSL 用户时连接失败?先检查服务端是否真启用了 SSL
很多用户配完 CREATE USER 'u'@'%' REQUIRE SSL; 就连不上,根本原因是 MySQL 实例压根没加载 SSL 证书——require_secure_transport=ON 是全局开关,但更底层的是 ssl_mode=DISABLED(默认值)导致整个服务不提供 SSL 握手能力。
实操建议:
- 执行
SHOW VARIABLES LIKE 'have_ssl';,必须返回YES;若为DISABLED,说明 OpenSSL 库未加载或配置缺失 - 确认
ssl_ca、ssl_cert、ssl_key三个系统变量非空,路径需是 MySQL 进程可读的绝对路径(如/etc/mysql/ssl/ca.pem),不能用相对路径或符号链接 - Linux 下常见坑:SELinux 或 AppArmor 拦截了 mysqld 对证书文件的访问,临时关闭 SELinux 测试(
setenforce 0)能快速验证是否为此类权限问题
客户端用 mysql -u user -p --ssl-mode=REQUIRED 还报 SSL connection error: protocol version mismatch?版本和 cipher 不匹配
MySQL 8.0 默认启用 TLSv1.2+,但老客户端(如 MySQL 5.7 客户端、某些 JDBC 驱动旧版)可能只支持 TLSv1.0,握手直接失败。错误里“protocol version mismatch”不是指服务端没开 SSL,而是双方 TLS 协议栈对不上。
实操建议:
- 服务端检查
tls_version变量(SELECT @@GLOBAL.tls_version;),MySQL 8.0.28+ 默认是TLSv1.2,TLSv1.3;如需兼容旧客户端,可设为TLSv1,TLSv1.1,TLSv1.2(不推荐生产环境长期使用) - 客户端显式指定协议:MySQL 命令行加
--ssl-fips-mode=OFF --tls-version=TLSv1.2;Java JDBC URL 加&enabledTLSProtocols=TLSv1.2 - 避免用自签名证书 +
--ssl-mode=VERIFY_IDENTITY,客户端会校验 CN 域名,而自签证书通常 CN 是 localhost,与实际连接地址不一致,直接拒绝连接
GRANT …… REQUIRE SSL 和 REQUIRE X509、REQUIRE ISSUER 的区别在哪?别乱混用
很多人以为 REQUIRE SSL 就是“强制加密”,其实它只确保传输层加密,不校验客户端身份;真正做双向认证得用 X509 系列子句,但它们对证书链要求严格,一环出错就登录失败。
实操建议:
-
REQUIRE SSL:只要求连接走 TLS,适合内部网络加密传输,不依赖客户端证书 -
REQUIRE X509:要求客户端提供有效证书(CA 签发、未过期、未吊销),但不对证书内容做任何校验 -
REQUIRE ISSUER 'CN=MyCA':强制校验证书签发者字段,注意必须完整匹配(包括空格、大小写),且 CA 证书必须已导入服务端ssl_ca - 混合写法如
REQUIRE SUBJECT 'CN=client1' AND X509很容易因 DN 格式差异(OpenSSL vs Java keytool 生成的 subject 不一致)导致匹配失败,调试时用openssl x509 -in client.pem -text -noout看真实 subject 字符串
应用连接池(如 HikariCP、Druid)配 useSSL=true 连不上?参数名和逻辑已变更
MySQL Connector/J 8.0+ 彻底废弃了 useSSL 参数,改用 sslMode;继续传 useSSL=true 不仅无效,还可能触发降级警告甚至静默禁用 SSL(取决于驱动版本)。
实操建议:
- JDBC URL 必须用
?sslMode=REQUIRED(不是useSSL=true),其他合法值包括DISABLED、REQUIRED、VERIFY_CA、VERIFY_IDENTITY - HikariCP 中不要在
dataSourceProperties里单独设useSSL,所有 SSL 相关参数应拼进jdbcUrl字符串 - Druid 1.2.16+ 支持
connectProperties: sslMode=REQUIRED,但低版本只认useSSL,升级驱动比硬改配置更可靠 - 连接池预热时若报
Could not connect to localhost:3306 : Could not create SSL context,大概率是 classpath 缺少javax.net.ssl.SSLContext所需的 JCE 策略文件(JDK 8u161+ 已内置,老 JDK 需手动替换)
最常被忽略的一点:MySQL 的 REQUIRE SSL 只作用于该用户的连接行为,但服务端是否允许非 SSL 连接,最终由 require_secure_transport 全局变量控制。哪怕所有用户都设了 REQUIRE SSL,只要这个变量是 OFF,攻击者仍可用普通账号绕过——配完用户,务必执行 SET PERSIST require_secure_transport = ON;