写点什么

MySQL 8.0 的 Public Key Retrival 错误,毫无规律可言怎么破?

  • 2021-03-24
  • 本文字数:2513 字

    阅读完需:约 8 分钟

MySQL 8.0的Public Key Retrival错误,毫无规律可言怎么破?

一、背景介绍

近期笔者所在部门在使用 MySQL 时,经常会出现如下错误,且这个错误并不会一直出现,属于某种偶发性的错误:



笔者所在部门的连接数据库的方法有 JDBC、JDBCTemplate、C3P0 连接池和 Druid 连接池等技术,在这些连接实现方法上笔者都观察到出现过上述的错误。该错误有一定的特性,就是偶尔会出现该错误,该错误并不会一直出现,该错误的出现没有明显的规律。而且笔者发现,底层使用 JDBC 连接驱动的情况下,无论上层是采用何种数据源实现技术,笔者的部门都发现会报上述错误。


针对上述错误,在笔者所在部门的软硬件环境下,笔者对 MySQL 为何会产生这个问题、这个问题产生的条件、MySQL 官方文档对这个问题的阐述、如何有效避免与解决这个问题等方面在本文进行了详细的分析与解释。希望能够帮助到真正遇到这个问题的 DBA 与开发人员。


二、环境介绍

1、实验构架

笔者所在部门使用的 MySQL 版本为 8.0.18 版本,MySQL 使用组复制技术保证高可用,即 MySQL Group Replication(MGR)。笔者复现问题以及实验的架构如下图所示:



图 2.1  实验所采用的构架


本测试使用的 MySQL MGR 集群搭建在虚拟机之上,虚拟机的详细硬件配置如下表所示:



表 2.1  详细硬件配置


为了充分测试各种类型的连接数据库的方式在笔者所在部门使用的 MySQL 上的表现,笔者分别测试 JDBC、JDBCTemplate、C3P0 以及 Druid 方式连接数据库,参与测试的软件版本如下表所示:



表 2.2  参与测试的软件版本

三、问题报错展示

在使用 JDBC 连接时,可能会出现“Public Key Retrieval is not allowed”的错误,从错误的 Java 堆栈信息中可以看出,该错误是在 JDBC 与 MySQL 建立 Connection 对象时出现的,该错误的错误堆栈如下图所示:



图 3.1  JDBC 错误堆栈


在使用 C3P0 连接池时,也会出现“Public Key Retrieval is not allowed”的错误,从错误的 Java 堆栈信息中可以看出,该错误仍是在 JDBC 与 MySQL 建立 Connection 对象时出现,该错误会导致 C3P0 连接池在初始化时失败,该错误的错误堆栈如下图所示:



图 3.2  C3P0 错误堆栈


在使用 Druid 连接池时,也会出现“Public Key Retrieval is not allowed”的错误,与 C3P0 连接池一样,会导致 Druid 连接池在初始化时失败,该错误的错误堆栈如下图所示:



图 3.3  Druid 错误堆栈

四、问题分析

笔者在查阅了网上关于“Public Key Retrieval is not allowed”错误的资料后,发现大多数网上关于该问题的博文对该问题的解释都存在一定的纰漏。首先需要明确的是出现该问题的时候,MySQL 配置的密码认证插件为如下两种:


  • sha256_password

  • caching_sha2_password


值得注意的是,如果使用“mysql_native_password”密码认证插件,不会出现“Public Key Retrieval is not allowed”错误。MySQL 配置的密码认证方式可以通过如下命令进行查看。



接着笔者来详细分析“Public Key Retrieval is not allowed”错误产生的原因。首先 MySQL 8.0 默认推荐使用“sha256_password”和“caching_sha2_password”这两种认证插件。只有较老的 MySQL 版本仍然会使用“mysql_native_password”。

根据 MySQL 提供的官方文档(https://dev.mysql.com/doc/refman/8.0/en/caching-sha2-pluggable-authentication.html),这两种插件都是使用 SHA256 算法来对密码进行保护。这些插件的具体执行流程如下:


  1. 检查客户端是否禁用 SSL/TLS 加密传输;

  2. 如果客户端未禁用 SSL/TLS 加密传输,则客户端在进行认证时的认证报文(传输用户名和密码的报文)是使用 TLS 进行传输的,两种插件认为认证报文传输安全,不进行任何其他操作;

  3. 如果客户端禁用 SSL/TLS 加密传输,则客户端在进行认证时的认证报文(传输用户名和密码的报文)是使用明文进行传输的,两种插件认为认证报文传输不安全,会单独对明文报文中的密码使用 RSA 加密方式进行加密。

1、启用 SSL/TLS 加密传输的客户端认证流程

如上述流程所述,当客户端未禁用 SSL/TLS 加密传输时,通过 Wireshark 等抓包工具可以观察到整个客户端与 MySQL 服务端交互的过程都被 TLS 协议加密保护了。如下图所示:



图 4.1  启用 TLS 协议 MySQL 传输报文


虽然会产生登录的明文报文,但是该明文报文中的用户信息为空,真正的用户信息在 TLS 握手阶段后的密文中。如下图所示:



图 4.2  启用 TLS 协议 MySQL 登录数据包详情

2、禁用 SSL/TLS 加密传输的客户端认证流程

如上述流程所述,当客户端禁用 SSL/TLS 加密传输时(比如 JDBC 连接串设置 useSSL=false 参数),用户的登录信息会在明文中进行传输,如下图所示:



图 4.3  禁用 TLS 协议 MySQL 传输报文


明文传输密码存在安全问题,此时,两种插件会尝试使用 RSA 加密(RSA encryption)方法对明文报文中的密码部分进行加密,加密后的密码部分如下图所示:



图 4.4  启用 TLS 协议 MySQL 登录数据包详情

五、解决方案

根据前面的分析,导致“Public Key Retrieval is not allowed”主要是由于当禁用 SSL/TLS 协议传输后,客户端会使用服务器的公钥进行传输,默认情况下客户端不会主动去找服务器拿公钥,此时就会出现上述错误。


经过查阅官方文档,出现 Public Key Retrieval 的场景可以概括为在禁用 SSL/TLS 协议传输切当前用户在服务器端没有登录缓存的情况下,客户端没有办法拿到服务器的公钥。具体的场景如下:


  1. 新建数据库用户,首次登录;

  2. 数据库的用户名、密码发生改变后登录;

  3. 服务器端调用 FLUSH PRIVELEGES 指令刷新服务器缓存。


针对上述错误,有如下的解决方案:


  1. 在条件允许的情况下,不要禁用 SSL/TLS 协议,即不要在 CLI 客户端使用--ssl-mode=disabled,或在 JDBC 连接串中加入 useSSL=false;

  2. 如果必须禁用 SSL/TLS 协议,则可以尝试使用 CLI 客户端登录一次 MySQL 数据库制造登录缓存;

  3. 如果必须禁用 SSL/TLS 协议,则可以通过增加如下参数允许客户端获得服务器的公钥:


  • 在 JDBC 连接串中加入 allowPublicKeyRetrieval=true 参数;

  • 在 CLI 客户端连接时加入--get-server-public-key 参数;

  • 在 CLI 客户端连接时加入--server-public-key-path=file_name 参数,指定存放在本地的公钥文件。


作者介绍

农行研发中心“数风云”团队,一支朝气蓬勃、快速成长的技术团队,始终致力于农行大数据、数据库和云计算等领域的应用实践与技术创新,探索数据赋能,勇攀数据云巅,为企业数字化转型和金融科技发展不断贡献力量。


本文转载自:dbaplus 社群(ID:dbaplus)

原文链接:MySQL 8.0的Public Key Retrival错误,毫无规律可言怎么破?

2021-03-24 07:003506

评论 2 条评论

发布
用户头像
都是内网访问数据库,或者同一个VPC,同一个机房之类的,SSL不必要吧
2021-03-26 14:10
回复
用户头像
看来不用SSL,数据库登陆很危险啊。
2021-03-26 11:43
回复
没有更多了
发现更多内容

OpenAI 或将推出多模态人工智能数字助理;研究发现部分 AI 系统已学会「说谎」丨 RTE 开发者日报 Vol.203

声网

为什么推荐将 IoTDB 服务地址配置为 HostName 而非 IP?

Apache IoTDB

低代码与Web开发:颠覆传统模式的现代技术

快乐非自愿限量之名

前端 Web 低代码

从零开始:使用 Playwright 脚本录制实现自动化测试

霍格沃兹测试开发学社

人类将会永生?谷歌 DeepMind重磅发布Alphafold 3 ——天花板级别的AI系统

GPU算力

深度学习 DeepMind 生物信息学 AlphaFold 蛋白质预测

Django性能之道:缓存应用与优化实战

不在线第一只蜗牛

sqlite django 缓存

建木Hub流水线正式版上线啦!!限时送200分钟体验时长

都广科技

DevOps

从XML配置角度理解Spring AOP

快乐非自愿限量之名

Java xml spring

虚拟仿真云实训平台:更优质的教育资源服务

3DCAT实时渲染

虚拟仿真 实时渲染 仿真云

DevOps与低代码:重塑软件开发与运维新时代

EquatorCoco

DevOps 运维 低代码

Postgresql查询每个月最后一天的数据||查询每个月数据中的最后一条数据

李爽

postgresql #SQL

免费的集成组件有哪些?

RestCloud

ETL 数据集成 ETLCloud

精准记录:使用 Playwright 实现屏幕截图

霍格沃兹测试开发学社

字节面试:说说Java中的锁机制?

王磊

Java 面试

【YashanDB知识库】ycm托管数据库时,数据库非OM安装无法托管

YashanDB

yashandb 崖山数据库 崖山DB

有了1688跨境接口,没有1688代采系统怎么办?

tbapi

1688API接口 1688代采系统

NFTScan | 05.06~05.12 NFT 市场热点汇总

NFT Research

NFT NFT\ NFTScan

Qualcomm CPU: IPQ9574, IPQ9554 and IPQ5322, what do you know?

wifi6-yiyi

WiFi7 ipq9574

低代码与AI技术发展:开启数字化新时代

不在线第一只蜗牛

人工智能 AI 低代码

巴黎奥运会:在线观看赛事直播平台开发与数据获取方法

软件开发-梦幻运营部

国标参编征集 | 关于公开征集《物流企业数字化 第二部分:平台架构》国家标准起草单位的通知

信通院IOMM数字化转型团队

数字化转型 物流

我,古希腊掌管「智算」的神!

白洞计划

AI 智算

容器技术:优化软件测试流程的利器

霍格沃兹测试开发学社

特权账号管理的那些坑

芯盾时代

iam 统一身份认证 特权账号管理

探索车路云深度融合的优化与实践

观测云

人工智能

个人名片升级攻略:ChatGPT助您塑造独特简历风格

测试人

软件测试 简历 ChatGPT

大厂技术同学的落地困境

老张

团队管理 职业规划 职场发展 大厂求职

探索未知:风靡硅谷开发者的 Unstructured Data Meetup 即将登陆中国

Zilliz

AI 非结构化数据 Meetup Zilliz

解锁弹框:Python 下的 Playwright 弹框处理完全指南

霍格沃兹测试开发学社

MySQL 8.0的Public Key Retrival错误,毫无规律可言怎么破?_编程语言_dbaplus社群_InfoQ精选文章