共计 1760 个字符,预计需要花费 5 分钟才能阅读完成。
作者:胡呈清
爱可生 DBA 团队成员,善于故障剖析、性能优化,集体博客:https://www.jianshu.com/u/a95…,欢送探讨。
本文起源:原创投稿
* 爱可生开源社区出品,原创内容未经受权不得随便应用,转载请分割小编并注明起源。
在客户那边遇见过几次这样的问题,Java 连贯 MySQL8.0 偶然 会报错:java.sql.SQLNonTransientConnectionException: Public Key Retrieval is not allowed
。网上一搜这个报错,早有人踩过这个坑:
如果用户应用了 sha256_password 认证,明码在传输过程中必须应用 TLS 协定爱护,然而如果 RSA 公钥不可用,能够应用服务器提供的公钥;能够在连贯中通过 ServerRSAPublicKeyFile 指定服务器的 RSA 公钥,或者 AllowPublicKeyRetrieval=True 参数以容许客户端从服务器获取公钥;然而须要留神的是 AllowPublicKeyRetrieval=True 可能会导致歹意的代理通过中间人攻打(MITM)获取到明文明码,所以默认是敞开的,必须显式开启。
原始文档如下:
JDBC 增加参数 AllowPublicKeyRetrieval=True 后的确解决了问题,然而留神前边说的“偶然”两字,我遇见了大略三种状况,在这之前一点问题都没有,但一产生就会报错:
1.MySQL Server 重启了;
2.MySQL MGR 产生切换了;
3.DBA 对 MySQL Server 做了某些变更后。
那后面的解释就显得有点不够了,尤其是第 3 点,开发肯定会感觉这是 MySQL 层面的问题或者 DBA 的问题,而不是他们对 MySQL 驱动理解不够。上面就为大家揭晓答案。
caching_sha2_password
MySQL8.0 默认应用明码加密插件为:caching_sha2_password,应用 sha256 算法对明码加密。而且在应用此插件时,MySQL Server 会在内存中缓存用户的认证信息,使已连贯的用户的身份验证速度更快,文档形容:
这个缓存的说法就很暧昧了,当然因为文档上没有更多形容,咱们只能先做假如:Java 程序通过驱动连贯到 MySQL 时,如果 MySQl Server 有用户的验证缓存,则不须要额定配置 RSA 公钥即可连贯胜利;如果没有缓存也没有指定 RSA 公钥,则连贯报错:Public Key Retrieval is not allowed
。
有了假如,咱们就要去论证,实际上论证的办法就是测试。
测试过程
测试代码:
编译后运行,间接复现报错:
接下来手工应用 mysql 客户端,用代码中的 user1 用户连贯 MySQL 服务器,使其产生缓存(这个操作就是管理员创立了利用用户后,手工验证了利用用户是否可登录):
而后再次运行 java 程序,将不再报错:
而后重启数据库,再次运行程序触发报错:
再次手工连贯,尽管程序恢复正常:
执行 flush privileges;
;操作清空用户缓存,随后运行程序再次报错:
MGR 产生切换的场景就很容易解释了,因为之前始终没有应用利用用户连贯过新的 Primary 节点,所以也就没有产生过缓存,所以应用程序连贯新的 Primary 节点会产生报错。
论断
一开始,在 MySQL Server 上创立利用用户后,手工应用 mysql 客户端对利用用户进行了验证,MySQL Server 缓存了利用用户的验证信息。应用程序的 JDBC 参数设置在没有指定 RSA 公钥和设置 AllowPublicKeyRetrieval=True 的状况下,连贯 MySQL Server,因为 MySQL Server 有用户缓存,所以能够失常连贯。
之后如果产生以下几种状况:
1.MySQL Server 重启了;
2.MySQL MGR 产生切换了;
3.DBA 对 MySQL Server 做了 flush privileges;
。
会导致 MySQL Server 的用户缓存生效,应用程序连贯 MySQL 异样:Public Key Retrieval is not allowed。
解决方案
以下计划抉择一种即可:
1. 应用程序指定 RSA 公钥;
2. 应用程序设置 AllowPublicKeyRetrieval=True;
3.MySQL Server 层批改用户的明码加密插件为 mysql_native_password。