JDBC连接mysql8:Public Key Retrieval is not allowed

笔记

情况是使用mysql8版本的数据库,某天突然启动时就报错了Public Key Retrieval is not allowed,然后可能又莫名其妙的好了。

刚开始别人说可能是jar版本不对没更新,感觉不像,我本地测试复现了几种情况,证实跟mysql-connector-java的版本无关

查了一篇文章写得比较详细 原文传送门=>

分析

出现这个报错的原因,大概就是因为mysql服务器版本升级之后,用户默认的密码存储方式是SHA256,由于安全限制,所以服务器会拒绝不安全的连接请求(默认)

CachingSha2PasswordPlugin.java源文件里:

// version: 8.0.29
if (!this.protocol.getPropertySet().getBooleanProperty(PropertyKey.allowPublicKeyRetrieval).getValue()) {
    throw ExceptionFactory.createException(UnableToConnectException.class,
        Messages.getString("Sha256PasswordPlugin.2"),
        this.protocol.getExceptionInterceptor());
}
// version: 5.1.47
if (!this.connection.getAllowPublicKeyRetrieval()) {
    throw SQLError.createSQLException(Messages.getString("Sha256PasswordPlugin.2"),
        SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE,
        this.connection.getExceptionInterceptor());
}

所以要么开启SSL安全连接验证,由安全协议来交互登录;
要么就要显式声明允许自动获取服务器公钥,让connector自动请求获取公钥,否则就会有Public Key Retrieval is not allowed异常。

按传送门的说法,还有一种是,手动在mysql服务器上登录一次缓存用户访问控制数据(具体原理不清楚,大概是用户在mysql客户端可以直接登录(navicat等也算),然后服务端有用户访问控制列表,验证成功后会更新user的状态缓存,之后其他connector就可以直接连接了,具体原理还是不清楚,但是实测确实可以)。

但是感觉不可靠,随时可能被flush privileges刷掉(复现测试,在服务器刷新权限后,直接使用connector依然会报错,每次都需要再重复一次上面的操作)。

所以解决方法有两个:

  1. 开启SSL,直接安全通信 useSSL=true,缺点是配置相对麻烦,要提供证书秘钥等相关数据
  2. 显式声明允许自动获取服务器公钥数据 allowPublicKeyRetrieval=true,缺点是安全性不足,可能被“中间人”拦截逆向获取明文密码(中间人攻击)。

扩展

基于上面的分析,其实之所以会突然出现上述问题(升级mysql版本后),还是因为用户密码的存储方式发生了变化。老版本可能设置的是mysql_native_password,密码存储和验证就是原始密码,而改为sha2加密后,就有安全性限制了。
所以,也可以在创建用户/修改密码的时候,主动声明密码格式:

ALTER USER 'dev'@'host' IDENTIFIED WITH mysql_native_password BY 'pwd';

这样就跟老版本的使用没区别了。

上面几种情况,各中取舍就要看具体的需求了。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值