Java应用出现Public Key Retrieval is not allowed错误,是什么配置或代码问题导致的?

摘要:Java 应用报错 Public Key Retrieval is not allowed,原来是 caching_sha2_password 插件惹的祸!
问题现象 Java 应用在运行过程中突然报java.sql.SQLNonTransientConnectionException: Public Key Retrieval is not allowed错误。 开发童鞋表示不理解,毕竟应用没做任何变更,为什么会突然出现这个错误? 2025-03-3108:31:11- create connection SQLException, url: jdbc:mysql://10.0.1.86:3306/information_schema?useSSL=false, errorCode 0, state 08001 java.sql.SQLNonTransientConnectionException: Public Key Retrieval is not allowed at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:110) at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:828) at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:448) at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:241) at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:198) at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1682) at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1803) at com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:2914) ... 问题原因 用户使用的密码认证插件是 caching_sha2_password 且 JDBC 连接串中指定了useSSL=false。 当碰到以下场景,就会出现上述报错: 第一次连接时。 数据库实例发生了重启。 服务端执行了 FLUSH PRIVILEGES 操作。 解决方法 解决方法有以下几种: 方案 1 将用户的密码认证插件调整为 mysql_native_password。不推荐该方法,因为 MySQL 9.0 移除了 mysql_native_password。 ALTERUSER'u1'@'%'IDENTIFIEDWITHmysql_native_passwordBY'MySQL@2025'; 方案 2 在 JDBC 连接串中设置useSSL=true。推荐该方法,但开启 SSL 会有一定的性能开销。 如果既不想开启 SSL,又想避免 Public Key Retrieval is not allowed 错误,以下是两个可选的解决方案: 方案 3 在 JDBC 连接串中添加allowPublicKeyRetrieval=true。 该方法会自动从 MySQL 服务端获取 RSA 公钥,但这种方法有一定的安全风险,可能会受到中间人攻击。攻击者可以伪造 RSA 公钥,窃取用户密码。 方案 4 在 JDBC 连接串中指定serverRSAPublicKeyFile。 该方法需要将方案 3 中的公钥内容写到应用侧的一个本地文件中,具体步骤如下: 通过show status like 'Caching_sha2_password_rsa_public_key'命令或者从参数 caching_sha2_password_public_key_path(默认是 public_key.pem)指定的文件中获取公钥内容。
阅读全文