REQUIRE SSL不生效主因是服务端未启用SSL或客户端连错实例;需先查have_ssl=YES及ssl_ca/cert/key路径有效,再确认用户创建语法、认证插件兼容性,并用STATUS或performance_schema验证实际加密连接。

MySQL 8.0+ 中 REQUIRE SSL 不生效的常见原因
直接说结论:REQUIRE SSL 不生效,大概率不是语法写错了,而是服务端压根没启用 SSL 支持,或者客户端连的压根不是你认为的那个实例。
检查的第一步永远是确认 MySQL 实例是否真的加载了证书:
- 执行
SHOW VARIABLES LIKE '%ssl%';,重点看have_ssl值必须是YES(不是DISABLED或NO) -
ssl_ca、ssl_cert、ssl_key三个变量都必须有非空路径值,且文件真实存在、MySQL 进程有读权限 - 如果用的是 Docker 或云数据库(如 RDS),默认可能只开 TLS 1.2+ 但未启用完整 SSL 握手能力,
REQUIRE SSL会静默退化为普通连接
创建用户时 REQUIRE SSL 的写法与陷阱
语法本身很简单,但容易在权限继承和认证插件上翻车:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 正确写法:
CREATE USER 'app'@'%' REQUIRE SSL;或更严格地REQUIRE SUBJECT '/CN=app-client' - 错误高发点:如果该用户之前已存在,
ALTER USER ... REQUIRE SSL不会自动禁用旧连接;必须配合FLUSH PRIVILEGES;,且已有活跃连接不受影响 - 注意认证插件:MySQL 8.0 默认用
caching_sha2_password,它和 SSL 是正交的;但某些老客户端(如旧版 PHP mysqli)不支持该插件 + SSL 组合,会报Authentication plugin 'caching_sha2_password' cannot be loaded - 若强制兼容,可指定插件:
CREATE USER 'app'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd' REQUIRE SSL;
验证连接是否真走 SSL 的实操方法
别信配置,要看实际握手结果。最可靠的方式是登录后查会话状态:
- 用客户端连上去后,执行
STATUS;,看输出里有没有SSL: Cipher in use is这一行 - 或查系统表:
SELECT * FROM performance_schema.status_by_thread WHERE VARIABLE_NAME = 'Ssl_cipher';,非空即表示当前线程用了加密 - 命令行工具加
--ssl-mode=REQUIRED参数再连一次,如果失败,说明服务端 SSL 确实没通;如果成功但 STATUS 里没显示 SSL,可能是客户端自动降级了(比如指定了--ssl-mode=PREFERRED) - 抓包验证(进阶):用
tcpdump -i lo port 3306抓包,用 Wireshark 打开,过滤mysql,如果能看到明文SELECT就肯定没加密
自签名证书在生产环境的现实约束
开发测试用 mysql_ssl_rsa_setup 生成自签名证书没问题,但上线后会遇到硬性限制:
- Java 客户端(JDBC)默认校验 CA,需显式加参数:
?useSSL=true&requireSSL=true&verifyServerCertificate=true&trustCertificateKeyStoreUrl=file:/path/to/truststore.jks - Python 的
pymysql和mysql-connector-python行为不同:mysql-connector默认不校验服务端证书,必须手动设ssl_disabled=False+ssl_verify_cert=True - 云厂商 RDS 通常只提供公有 CA 签发的证书(如 AWS RDS 的
rds-ca-2019.pem),要求客户端必须配置对应 CA 文件,否则REQUIRE SSL会被绕过 - 证书过期不会导致 MySQL 启动失败,但新连接会拒绝——这个时间点很难监控,建议把证书有效期写进部署检查清单
真正难的不是配通,是让所有客户端组件(包括监控脚本、离线任务、旧 shell 脚本里的 mysql -e)都带上正确的 SSL 参数,漏一个就等于没锁住。

















