写点什么

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:003445

评论 2 条评论

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

初识 Flutter 的绘图组件 — CustomPaint

岛上码农

flutter ios 安卓 移动端开发 跨平台开发

分享一个修改了xml文件再也不用重启的项目mybatis-xmlrealod

越长大越悲伤

Java 开源 Spring Boot mybatis 开源项目

“找工难&金三银四”,关于面试,你需要知道的这些事

IT学习日记

面试 Java、 找工作 简历模板

复杂「场景」数据导入导出

Java 架构

Spring源码核心剖析

京东科技开发者

spring 前端 京东云 京东技术 企业号 3 月 PK 榜

安全测试之探索windows游戏扫雷

京东科技开发者

编程 windows 企业号 3 月 PK 榜 动态调式 代码编写

电商秒杀系统

Geek_7d539e

三天吃透MySQL面试八股文

程序员大彬

MySQL java面试

京东金融Android瘦身探索与实践

京东科技开发者

App 京东云 京东技术 企业号 3 月 PK 榜 京东科技

Github 爆火,阿里巴巴大牛都在强推的 Java 性能优化实践小册!

架构师之道

Java 编程 计算机

Gestures(手势)

梦笔生花

Activity 手势 gesturelistener

华为都入场做ERP了,国产ERP困局如何破解?

陈飞

分布式数据库 国产化 ERP SaaS 平台 PaaS平台

PyTorch 深度学习实战 | 知识图谱嵌入结合图路径的推荐 RippleNet

TiAmo

深度学习 Ripplenet

设计模式之美––依赖反转

GalaxyCreater

设计模式

华为P系列,雪夜梅花开,似是故人来

脑极体

华为

机器学习算法(六)基于天气数据集的XGBoost分类预测

汀丶人工智能

数据挖掘 数据分析 XGBoost

狼来了

俞凡

人工智能

SaaS 软件搞定客户的关键环节分析

产品海豚湾

产品经理 SaaS 产品运营 B 端产品 互联网产品

多功能文件搜索软件:HoudahSpot中文版

真大的脸盆

Mac Mac 软件 文件搜索 搜索工具 搜索文件

2023年最新互联网Java面试八股文出炉(附大厂P5-P8技术栈)

架构师之道

Java 程序员 面试

预约直播|3月30日下周四,应用促活大揭秘,快速提升DAU

HarmonyOS SDK

HMS Core

对于Vue3和Ts的心得和思考

京东科技开发者

Vue ts 京东云 京东技术 企业号 3 月 PK 榜

关于数据库分库分表的一点想法

京东科技开发者

数据库 ShardingSphere 京东云 京东技术 企业号 3 月 PK 榜

面试突击:MVCC 和间隙锁有什么区别?

王磊

java面试

有一种焦虑叫ChatGPT(62/100)

hackstoic

AI AIGC ChatGPT

DevOps 在未来将如何演进?丨行业观察

SEAL安全

DevOps 平台工程

Go 语言 new 和 make 关键字的区别

AlwaysBeta

面试 Go 语言

湃方科技联合CnosDB助力旋转类机械预测性维护

CnosDB

数据库 开源 时序数据库 CnosDB

通过 Amazon Managed Microsoft Active Directory 运行混合 Active Directory 服务

亚马逊云科技 (Amazon Web Services)

Amazon

详细分析Spring Boot启动流程

Java你猿哥

spring Spring Boot SpringBoot启动流程

备战金三银四:2023年1200道Java面试真题合集,助你搞定面试官

采菊东篱下

Java 面试

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