MySQL服务端SSL必须先启用,SHOW VARIABLES LIKE 'have_ssl'返回YES且ssl_ca/cert/key为非空绝对路径,否则REQUIRE SSL不生效;客户端需显式启用SSL模式,且require_secure_transport=ON才能全局强制加密。

直接给用户加 REQUIRE SSL 不生效,大概率是服务端 SSL 根本没真正启用——连握手都触发不了,不是权限问题,是协议层被拦在门外。
确认 MySQL 服务端 SSL 已真正启用
这是所有后续操作的前提。很多“配了连不上”的问题卡在这一步,而不是用户权限本身。
-
SHOW VARIABLES LIKE 'have_ssl';必须返回YES;若为DISABLED或空值,说明 OpenSSL 模块未加载或配置被忽略 -
SHOW VARIABLES LIKE 'ssl_%';中ssl_ca、ssl_cert、ssl_key三项必须是非空绝对路径(如/etc/mysql/ssl/ca.pem),不能是OFF、空字符串或相对路径 - 常见静默失败原因:
server-key.pem权限不是600、属主不是mysql用户、SELinux/AppArmor 拦截读取、路径写在[client]段而非[mysqld]段 - 检查错误日志(
mysqld.log),搜索SSL或error,常有类似Failed to set up SSL because of SSL library error的提示
给已有用户添加 REQUIRE SSL 权限
服务端 SSL 启用后,才可对用户生效 REQUIRE SSL 策略。它只控制该用户的连接是否必须加密,不提供双向认证。
- MySQL 5.7 支持对已有用户执行:
ALTER USER 'appuser'@'10.0.2.%' REQUIRE SSL; - 执行后必须运行
FLUSH PRIVILEGES;,否则旧连接可能仍缓存旧权限状态 - 验证是否生效:
SELECT user, host, ssl_type FROM mysql.user WHERE user = 'appuser';,ssl_type应为ANY - 注意:如果用户是通过
localhost或 Unix socket 连接,REQUIRE SSL不起作用——本地连接不走 TCP,不参与 TLS 握手
客户端连接必须显式启用 SSL 模式
即使用户设了 REQUIRE SSL,客户端不主动发起 TLS 握手,连接仍会被拒绝——这不是认证失败,是协议层被拦在门外。
- 命令行连接必须加参数:
mysql -u appuser -h 192.168.1.100 -p --ssl-mode=REQUIRED(MySQL 5.7 中--ssl已弃用,行为不一致) - JDBC URL 需完整声明:
?useSSL=true&requireSSL=true&enabledTLSProtocols=TLSv1.2(旧驱动用usessl=true无效) - PHP PDO 连接需在 DSN 中加入
;sslmode=require或指定证书路径 - 避免用
--ssl-mode=VERIFY_IDENTITY配自签名证书:客户端会校验 CN 域名,而自签证书 CN 通常为localhost,与真实 IP 或域名不匹配,直接拒连
require_secure_transport=ON 是全局兜底开关
仅靠用户级 REQUIRE SSL 不够,远程 TCP 连接仍可能绕过。要真正“一刀切”禁用明文连接,必须开启全局开关。
- 运行时启用(推荐):
SET PERSIST require_secure_transport = ON;(MySQL 5.7.31+ 支持PERSIST) - 或在
my.cnf的[mysqld]段添加:require_secure_transport=ON,然后重启 - 开启后,所有非本地(非
localhost/ socket)TCP 连接都必须满足 TLS 握手,否则直接拒绝,连Access denied都不会报——连接在协议层就被断开 - 这个设置会影响所有用户,包括 root 和监控账号,务必提前测试客户端兼容性
最容易被忽略的是:服务端证书私钥权限不对、客户端没加 --ssl-mode=REQUIRED、以及误以为 localhost 连接也受 REQUIRE SSL 约束。这三处一错,整个强制策略就形同虚设。


















