mysql 5.7 中 alter user ... require ssl 不生效的主因是服务端 ssl 未真正启用:have_ssl=no/disabled、ssl_ca等变量为空、证书路径非绝对或权限/属主错误(需mysql用户+600)、配置未写在[mysqld]段、未重启mysqld。

MySQL 5.7 中 ALTER USER ... REQUIRE SSL 不生效的常见原因
配置后仍能明文登录,基本不是语法错,而是服务端 SSL 根本没真正启用。have_ssl 显示 YES 也不代表就绪——它只说明 MySQL 编译时支持 SSL,不反映运行时证书加载状态。
-
ssl_ca、ssl_cert、ssl_key变量值为空或路径不存在 → 证书未加载,REQUIRE SSL自动失效 - 私钥文件(如
server-key.pem)属主不是mysql用户,或权限 >600 → mysqld 启动时静默跳过 SSL 初始化 - 配置写在
[client]或[mysql]段,而非[mysqld]→ 完全无效 - 未重启 mysqld,仅执行
SET GLOBAL→ 所有 SSL 相关变量均为只读,无法动态开启
生成并验证证书是否被 mysqld 正确加载
用 mysql_ssl_rsa_setup 是最稳的方式,但必须指定目标目录并确保权限干净:
- 先停库:
systemctl stop mysqld - 创建独立证书目录(不混入 datadir):
mkdir -p /etc/mysql/ssl && chown mysql:mysql /etc/mysql/ssl && chmod 700 /etc/mysql/ssl - 生成证书:
mysql_ssl_rsa_setup --datadir=/etc/mysql/ssl --uid=mysql - 收紧私钥权限:
chmod 600 /etc/mysql/ssl/server-key.pem && chown mysql:mysql /etc/mysql/ssl/server-key.pem
然后在 /etc/my.cnf 的 [mysqld] 段写死路径:
ssl-ca = /etc/mysql/ssl/ca.pem ssl-cert = /etc/mysql/ssl/server-cert.pem ssl-key = /etc/mysql/ssl/server-key.pem
重启后立刻验证:SHOW VARIABLES LIKE 'ssl%'; 确保三个路径非空;再执行 \s,看到 SSL: Cipher in use is ... 才算真正就绪。
用户级强制 SSL 的正确写法与验证方式
REQUIRE SSL 是最轻量也最可靠的客户端强制手段,但要注意它只对新连接生效,且不校验证书内容(只校验 TLS 握手成功):
- 创建用户时直接加限制:
CREATE USER 'appuser'@'10.20.%' REQUIRE SSL; - 已有用户改限制:
ALTER USER 'appuser'@'10.20.%' REQUIRE SSL; - 必须配套
GRANT权限,否则登录后无权做任何事:GRANT SELECT ON mydb.* TO 'appuser'@'10.20.%';
验证是否生效:用明文方式连接会直接报错 Access denied for user ... (using password: YES)(注意不是 SSL error),而加 --ssl-mode=REQUIRED 才能连上。别信客户端日志里 “SSL enabled” 字样——只有服务端拒绝明文连接,才算真正卡住入口。
客户端连接时容易忽略的降级陷阱
即使服务端配了 REQUIRE SSL,客户端不主动协商 TLS,连接依然会降级为明文(MySQL 5.7 默认行为)。这不是 bug,是设计:
- 命令行必须显式加参数:
mysql -u appuser -p --ssl-mode=REQUIRED(--ssl在 5.7 已弃用,行为不可靠) - JDBC URL 必须带
?useSSL=true&requireSSL=true&verifyServerCertificate=true,且需提供trustCertificateKeyStoreUrl - 应用代码里若用
mysql_real_connect(),必须设MYSQL_OPT_SSL_MODE为SSL_MODE_REQUIRED,不能只设MYSQL_OPT_SSL_CA
最隐蔽的问题是:本地 localhost 连接默认走 socket,完全绕过网络层和 SSL。测试时务必用 -h 127.0.0.1 或真实 IP,否则永远验证不到效果。











