结论是:这不是客户端 bug,而是 MySQL 8.0 默认启用 caching_sha2_password 后强制要求非 SSL 连接必须显式允许 RSA 公钥获取(allowPublicKeyRetrieval=true),否则因 CVE-2021-29847 修复而拒绝连接;安全生产环境应启用完整 SSL 验证而非降级使用 allowPublicKeyRetrieval。

直接说结论:这不是客户端 bug,是 MySQL 8.0 默认启用 caching_sha2_password 插件后,对非 SSL 连接施加的 RSA 公钥安全策略。不改配置或用户认证方式,连接必然失败。
为什么加了 useSSL=false 就报 “Retrieval of the RSA public key is not enabled for insecure connection”?
MySQL 8.0.28+ 驱动(如 mysql-connector-java:8.0.33+)默认禁止在明文连接中自动拉取服务器公钥——这是 CVE-2021-29847 的修复措施,不是疏漏。只要满足三个条件就会触发:useSSL=false + 用户用 caching_sha2_password 认证 + 驱动未显式允许公钥获取。
常见错误现象:
- Spring Boot 启动时抛
SQLNonTransientConnectionException: Public Key Retrieval is not allowed - DBeaver 编辑连接后测试失败,提示同上
- Navicat 报 “RSA public key retrieval is not enabled” 且无法勾选“使用 SSL”选项
allowPublicKeyRetrieval=true 能不能直接加?
能,但必须清楚代价:
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
- 仅限本地开发或内网可信环境;生产环境禁用
- 加了它却没配
useSSL=true,等于把密码加密过程暴露给中间人——攻击者可截获 RSA 加密后的密文,再用拉到的公钥解出明文密码 - 参数名大小写敏感:
allowPublicKeyRetrieval(不是allowpublickeyretrieval),且必须和useSSL=false同时出现才生效 - 示例 JDBC URL:
jdbc:mysql://localhost:3306/test?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
怎么永久切换回 mysql_native_password 认证?
这是兼容旧驱动最稳妥的做法,但需 DBA 权限执行 SQL:
- 登录 MySQL(用 root 或有
ALTER USER权限的账号) - 执行:
ALTER USER 'your_user'@'%' IDENTIFIED WITH mysql_native_password BY 'your_password'; - 立即生效,无需重启 MySQL;但已有连接需重连
- 注意:若用户 host 是
'your_user'@'localhost',不能简写为'your_user'@'127.0.0.1',两者权限记录独立 - 批量修改所有用户(不推荐):
SELECT CONCAT('ALTER USER ''', user, '''@''', host, ''' IDENTIFIED WITH mysql_native_password BY ''', authentication_string, ''';') FROM mysql.user WHERE plugin = 'caching_sha2_password';,再逐条执行结果
生产环境该用哪种方案?
唯一推荐路径:启用 SSL 并关闭公钥检索。
- MySQL 服务端开启
require_secure_transport=ON(my.cnf中配置并重启) - 客户端连接时设
useSSL=true&verifyServerCertificate=true,并提供 CA 证书路径(trustCertificateKeyStoreUrl等) - 此时
allowPublicKeyRetrieval必须为false(默认值),否则驱动会拒绝连接 - 如果暂时无法部署完整 SSL,至少把
useSSL=true和allowPublicKeyRetrieval=false同时设上——驱动会 fallback 到 SSL 握手阶段协商密钥,绕过 RSA 公钥流程
最容易被忽略的一点:很多团队以为加了 useSSL=true 就万事大吉,但没配证书验证,驱动实际走的是非验证模式(verifyServerCertificate=false),此时仍可能触发公钥检索限制。真要安全,CA 证书和验证开关缺一不可。

















