Public Key Retrieval is not allowed
这个错误通常发生在连接 MySQL 8.0 或更高版本的数据库时。其根本原因是客户端与服务器之间的认证机制不匹配,尤其是在未使用 SSL 加密连接的情况下。
🧐 错误原因分析
MySQL 8.0 为了增强安全性,默认采用了 caching_sha2_password 作为用户的认证插件。当客户端尝试连接时:
- 安全握手 :如果连接没有启用 SSL 加密(即
useSSL=false),客户端需要使用服务器的 RSA 公钥来加密密码,然后发送给服务器进行验证。 - 获取公钥:为了获取这个公钥,客户端会向服务器发起一个"公钥检索"请求。
- 默认禁止 :出于安全考虑(防止中间人攻击),JDBC 驱动等客户端默认是禁止自动检索公钥的。
因此,当你尝试用一个非 SSL 连接去连接一个使用 caching_sha2_password 认证的用户时,就会因为无法获取公钥而报错 Public Key Retrieval is not allowed。
✅ 解决方案
以下是几种常见的解决方法,你可以根据自己的环境(开发、测试或生产)选择最合适的一种。
方案一:修改连接字符串(适用于开发/测试环境)
这是最快速直接的解决方法。在你的 JDBC 连接 URL 中,显式地添加两个参数:allowPublicKeyRetrieval=true 和 useSSL=false。
allowPublicKeyRetrieval=true: 允许客户端从服务器检索公钥。useSSL=false: 明确禁用 SSL 连接。
配置示例:
-
JDBC URL:
jdbc:mysql://localhost:3306/your_database?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC -
Spring Boot (
application.properties):propertiesspring.datasource.url=jdbc:mysql://localhost:3306/your_database?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC spring.datasource.username=your_username spring.datasource.password=your_password -
Spring Boot (
application.yml):yamlspring: datasource: url: jdbc:mysql://localhost:3306/your_database?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC username: your_username password: your_password
⚠️ 安全警告 :此方法会降低连接的安全性,因为它允许在不加密的信道上交换公钥。强烈建议仅在本地开发或可信的内部测试环境中使用。
方案二:修改用户认证插件(兼容性方案)
将数据库用户的认证方式改回旧版的 mysql_native_password。这种方式不依赖 RSA 公钥进行密码加密,因此可以避免此问题。
你需要登录到 MySQL 数据库(可以使用命令行或其他已连接的客户端),然后执行以下 SQL 命令:
sql
-- 将 'your_user' 和 'your_host' 替换为你的实际用户名和主机
-- 将 'your_password' 替换为你的新密码
ALTER USER 'your_user'@'your_host' IDENTIFIED WITH mysql_native_password BY 'your_password';
FLUSH PRIVILEGES;
这个方法兼容性很好,但放弃了 caching_sha2_password 带来的更强安全性,可以作为临时或兼容性方案。
方案三:配置 SSL 加密连接(生产环境推荐)
在生产环境中,最佳实践是启用 SSL/TLS 加密连接。这样,密码等敏感信息会在加密通道中传输,无需通过不安全的公钥检索方式。
你需要配置有效的 SSL 证书,并在连接字符串中设置相关参数:
useSSL=true: 启用 SSL。requireSSL=true: 要求必须使用 SSL 连接。verifyServerCertificate=true: 验证服务器证书的有效性。
配置示例:
jdbc:mysql://localhost:3306/your_database?useSSL=true&requireSSL=true&verifyServerCertificate=true&...
这种方法安全性最高,符合生产环境的安全合规要求。