解决 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 驱动程序,更新用户的身份验证插件,或者显式允许公钥检索,你可以解决这个问题。 记住,安全性至关重要,请务必权衡各种解决方案的安全风险,并采取适当的措施来保护你的数据库。

在Java中,当你尝试使用JDBC(Java Database Connectivity)连接MySQL数据库,遇到"Public Key Retrieval is not allowed"这样的错误,通常表示JVM(Java Virtual Machine)不信任MySQL服务器的SSL证书。这是因为Java要求从HTTPS服务器获取并验证数字证书,以确保连接的安全性。 这个错误通常是由于以下原因: 1. **JVM配置不正确**:可能是你的系统没有设置允许JVM从不受信源获取SSL证书,或者JVM的SSL证书设置不支持从MySQL服务器获取证书。 2. **MySQL SSL配置**:MySQL可能没有正确配置SSL,或者证书路径设置不正确,导致JDBC驱动无法找到并验证证书。 3. **JDBC驱动版本**:过旧的JDBC驱动可能不支持SSL或证书管理,需要更新到最新版本。 为了解决这个问题,你可以尝试以下几个步骤: 1. **检查JVM配置**:确保`JAVA_OPTS`或`jvm.options`中没有禁止从不受信源获取证书的设置,如`-Djavax.net.ssl.trustStore=...` 和 `-Djavax.net.ssl.trustStorePassword=...`。 2. **获取并安装证书**:下载MySQL的SSL证书文件(通常是.pem格式),将其导入到Java的信任store中。 3. **更新JDBC驱动**:确保使用的JDBC驱动支持MySQL的SSL功能。 4. **修改MySQL SSL配置**:在MySQL的配置文件中(如my.cnf),设置正确的SSL选项,例如`ssl-ca`, `ssl-cert`, 和 `ssl-key`。 5. **重启服务**:配置更改后,需要重启MySQL服务使其加载新的SSL设置。 6. **测试连接**:重新尝试连接,看是否能够成功并且不再显示SSL相关的错误。 如果你正在使用Spring BootSpring Data JPA等框架,还需要检查相应的配置文件,因为它们可能提供了额外的配置选项。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值