解决 Spring Boot 连接 MySQL 时遇到的 “Public Key Retrieval is not allowed“ 错误

在使用 Spring Boot 开发应用,并连接 MySQL 数据库时,你可能会遇到一个令人头疼的错误:Public Key Retrieval is not allowed。 这个错误通常出现在你更新了 MySQL JDBC 驱动程序之后,或者在升级了 MySQL 服务器版本之后。 本文将深入分析这个错误的原因,并提供详细的解决方案,帮助你快速解决问题。

错误描述:

当你尝试连接 MySQL 数据库时,可能会在日志中看到以下错误信息:

java.sql.SQLNonTransientConnectionException: Public Key Retrieval is not allowed

这个错误通常伴随着以下异常堆栈:

com.mysql.cj.jdbc.exceptions.SQLError.createSQLException
com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException
com.mysql.cj.jdbc.ConnectionImpl.createNewIO

错误原因:

这个错误的核心原因是 MySQL 服务器拒绝客户端使用公钥检索的方式进行身份验证。 从 MySQL 8.0 版本开始,默认的身份验证插件从 mysql_native_password 更改为 caching_sha2_password。 caching_sha2_password 插件使用 SHA-256 进行密码哈希,并且默认情况下不允许客户端使用公钥检索的方式进行身份验证,以提高安全性。

解决方案:

以下是一些解决 "Public Key Retrieval is not allowed" 错误的方案,我们将按照推荐程度排序:

  1. 更新 MySQL JDBC 驱动程序(强烈推荐):

    • 这是最安全和最推荐的解决方案。 升级你的 MySQL JDBC 驱动到 8.0 或更高版本。 新版本的驱动程序支持 caching_sha2_password 插件,并且可以正确处理身份验证。

    • 在你的 Maven 或 Gradle 依赖项中更新 mysql-connector-java 的版本。

    • 确保你的 pom.xml (Maven) 或 build.gradle (Gradle) 文件中包含正确的依赖:

      <!-- Maven -->
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>8.0.33</version> <!-- 使用最新版本 -->
      </dependency>
      
      // Gradle
      implementation 'mysql:mysql-connector-java:8.0.33' // 使用最新版本
      
  2. 更新 JDBC 连接字符串中的驱动类名:

    • 确保你的 JDBC 连接字符串使用了正确的驱动类名 com.mysql.cj.jdbc.Driver

    • 在 Spring Boot 的 application.properties 或 application.yml 文件中,检查 spring.datasource.driver-class-name 属性是否正确配置。

      # application.properties
      spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
      
      # application.yml
      spring:
        datasource:
          driver-class-name: com.mysql.cj.jdbc.Driver
      
    • 同时,建议在 JDBC URL 中也明确指定驱动类名,以便更清晰地配置:

      jdbc:mysql://127.0.0.1:3306/hmdp?useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true&driverClassName=com.mysql.cj.jdbc.Driver
      
  3. 更新 MySQL 用户的身份验证插件:

    • 如果你的 MySQL 版本是 8.0 或更高版本,并且用户是在旧版本上创建的,升级到 8.0 后需要更新用户的身份验证插件。

    • 使用以下 SQL 命令更新用户的身份验证插件:

      ALTER USER 'your_user'@'your_host' IDENTIFIED WITH caching_sha2_password BY 'your_password';
      FLUSH PRIVILEGES;
      

      替换 your_useryour_host 和 your_password 为你的实际值。

  4. 显式允许公钥检索(不推荐,降低安全性): 本人更新了8.0.33后仍然错误,改为这样才解决

    • 作为最后的手段,你可以在 JDBC 连接字符串中显式地允许公钥检索。

    • 在你的 JDBC 连接字符串中添加 allowPublicKeyRetrieval=true

      jdbc:mysql://your_host:3306/your_database?allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true&driverClassName=com.mysql.cj.jdbc.Driver
      
    • 警告: 这种方法会降低安全性,因为它允许客户端从服务器检索公钥,这可能会受到中间人攻击。 只有在确定没有其他更好的解决方案时才考虑使用。

  5. 检查 MySQL 服务器配置:

    • 确保 MySQL 服务器没有强制禁用 caching_sha2_password 插件。
    • 检查 MySQL 服务器的配置文件 (my.cnf 或 my.ini),确保没有 default_authentication_plugin=mysql_native_password 这样的配置。 如果有,并且你希望使用 caching_sha2_password 插件,请删除或注释掉该配置,并重启 MySQL 服务器。
  6. 检查 MySQL 用户权限:

    • 确保你的 MySQL 用户有足够的权限连接到数据库。

    • 你可以使用以下命令检查用户的权限:

      SHOW GRANTS FOR 'your_user'@'your_host';
      
    • 确保用户有 CONNECT 权限,以及对数据库的 SELECTINSERTUPDATEDELETE 等权限。

最佳实践:

  • 优先选择更新 JDBC 驱动程序: 这是最安全和推荐的解决方案。
  • 在生产环境中启用 SSL 加密: 为了保护数据传输的安全性,强烈建议在生产环境中启用 SSL 加密 (useSSL=true)。
  • 使用安全的方式管理数据库密码: 避免将密码直接放在配置文件中。 使用环境变量、外部配置管理工具(例如 Spring Cloud Config、HashiCorp Vault)或加密工具来保护密码。
  • 定期更新依赖项: 保持你的 JDBC 驱动程序和其他依赖项更新到最新版本,以获得最新的安全修复和功能。

总结:

"Public Key Retrieval is not allowed" 错误通常是由于 MySQL 服务器的身份验证机制与你的 JDBC 驱动程序不兼容造成的。 通过更新 JDBC 驱动程序,更新用户的身份验证插件,或者显式允许公钥检索,你可以解决这个问题。 记住,安全性至关重要,请务必权衡各种解决方案的安全风险,并采取适当的措施来保护你的数据库。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值