REQUIRE SSL 不强制加密连接,仅在认证阶段校验SSL通道;未加密时认证失败但连接仍建立,需配合require_secure_transport=ON才能真正拦截明文连接。

REQUIRE SSL 本身不强制加密连接,它只在认证阶段检查通道是否已加密——客户端不主动启用 SSL,服务端不会拒绝连接,而是让认证失败。
REQUIRE SSL 的真实行为:不拦截明文连接,只校验认证时的通道状态
MySQL 的 REQUIRE SSL 不是网络层拦截器。它不会在 TCP 握手后主动断开未加密连接,而是在用户认证环节检查当前连接是否已建立 SSL 加密通道。如果没走 SSL,认证直接失败,报错:Access denied for user 'xxx'@'xxx' (using password: YES)(错误码 HY000),但连接本身仍能建立成功。
- 典型误判场景:用
mysql -u xxx -p直连成功,以为权限没生效——其实走的是明文,只是还没到认证校验那步就被跳过了(比如用了--ssl-mode=DISABLED或客户端自动降级) - 真正触发
REQUIRE SSL拦截,必须满足两个条件:① 连接已建立;② 认证发起时通道未加密 - localhost 用户默认走 Unix socket,完全绕过网络层和 SSL 检查,
REQUIRE SSL对其无效
如何验证 REQUIRE SSL 是否真正起效
不能只看 GRANT 语句是否执行成功,得用明确禁用 SSL 的方式触发失败:
- 执行
mysql -u xxx -p --ssl-mode=DISABLED,应报Access denied;若成功登录,说明权限未生效或被更宽松的同名用户覆盖(如'xxx'@'%'和'xxx'@'localhost'并存) - 查权限表确认:
SELECT user, host, ssl_type FROM mysql.user WHERE user = 'xxx';,ssl_type必须是ANY或X509,不是NONE - 注意:修改后需执行
FLUSH PRIVILEGES;,否则内存权限缓存未更新
REQUIRE SSL 配合 require_secure_transport 才算真正强制
REQUIRE SSL 是用户级控制,require_secure_transport = ON 是全局开关——后者才是服务端层面的硬性拦截,所有连接(包括 root、localhost)都必须走 SSL,否则直接拒绝 TCP 连接。
-
require_secure_transport = ON是 MySQL 5.7.17+ 引入的配置项,写在my.cnf的[mysqld]段落中,重启生效 - 开启后,即使用户没设
REQUIRE SSL,任何非 SSL 连接都会在 TCP 层被拒,错误日志里会出现Connection closed by remote host类提示 - 两者组合最稳妥:
require_secure_transport = ON拦所有连接,REQUIRE SSL再对特定用户加一层认证校验
常见失效原因:host 匹配优先级和权限叠加
MySQL 权限匹配按 user@host 最长匹配原则,REQUIRE SSL 很容易被更宽泛的条目覆盖:
- 如果存在
'xxx'@'%'(无 REQUIRE)和'xxx'@'192.168.1.%'(有 REQUIRE),客户端从192.168.1.100连入时,会匹配后者,REQUIRE SSL生效 - 但如果同时存在
'xxx'@'localhost'(无 REQUIRE),且客户端用-h 127.0.0.1连,实际走的是 TCP,但 host 匹配仍可能落到'xxx'@'localhost'上(取决于解析顺序),导致 REQUIRE 被忽略 - 用
SELECT USER(), CURRENT_USER();查看实际匹配的用户身份,比单纯查mysql.user更可靠
真正强制加密的关键不在 GRANT ... REQUIRE SSL 这一行语句,而在服务端是否启用了 require_secure_transport,以及客户端是否真的通过 TLS 协议完成了握手——证书链、TLS 版本、密钥权限这些底层细节出问题,REQUIRE SSL 就永远等不到它想校验的那个加密通道。











