ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

MySQL 8.0报错1251:认证协议不匹配的排查与解决方案

MySQL 8.0报错1251:认证协议不匹配的排查与解决方案 作为DBA或者后端开发这两年绕不开的一个经典报错就是mysql出现1251- Client does not support authentication protocol requested by server。尤其是刚装完MySQL 8.0兴冲冲打开Navicat、旧版MySQL Workbench或者跑一跑比较老的项目代码一连接就给你甩出这行英文翻译过来就是客户端不支持服务端请求的认证协议。很多新手在这一步就直接卡住以为是密码错了、服务没启动甚至开始重装数据库结果折腾一圈发现根本不是那回事。这篇文章就围绕这个1251报错把背后的认证机制、几种亲测有效的解决方案、还有容易踩的坑一次讲清楚。不管你是用Navicat连不上、JDBC驱动报错、还是Python/DBeaver连MySQL 8.0遇到同样问题按下面步骤操作基本都能解决。内容覆盖完整实操命令和排查思路适合刚接触MySQL的开发者也适合被这个问题困扰的运维和全栈工程师收藏。1. 1251报错到底是什么为什么会发生1.1 报错背后的认证机制先理解1251这个错误最本质的原因MySQL服务端的默认认证插件和客户端支持的认证插件不匹配。MySQL在8.0版本做了一个很重要的安全变更默认的认证插件从之前的mysql_native_password改成了caching_sha2_password。这个改动本身是好事因为caching_sha2_password基于SHA-256加密安全性更高还支持服务端和客户端之间更安全的密码交换机制。但问题在于很多老的客户端工具和编程语言驱动在MySQL 8.0刚发布那几年并没有及时跟进支持这个新插件。于是当老客户端试图连接新服务端时服务端说我要用caching_sha2_password来验证你客户端说我只会mysql_native_password两边谈不拢服务端就返回了1251 - Client does not support authentication protocol requested by server。这里有个容易混淆的点很多人把这个报错当成密码错误。实际上密码可能是完全正确的认证协议不匹配会导致服务端根本不会去校验你输入的密码内容直接就拒绝了连接。所以排查这个报错时不用反复去改密码、重置密码那是浪费时间。核心矛盾就是客户端太老、服务端太新两边支持的认证方式对不上。用一个生活化的类比服务端说我们见面需要刷脸验证身份客户端说我只有密码卡没有录入人脸那无论你的密码卡密码对不对门禁都不会让你进去。1251就是这个验证方式谈不拢的提示。1.2 为什么MySQL 8.0要改用caching_sha2_password知道了直接的触发原因再深挖一层为什么MySQL官方要强制推行这个新插件如果只是客户端兼容性问题官方完全可以像以前一样一直沿用mysql_native_password。关键考量是安全。mysql_native_password在密码验证过程中客户端会把密码的哈希值发送给服务端做比对这种机制采用的是SHA-1算法而SHA-1在密码学上已经被证明存在碰撞攻击的可能性不再被视为安全哈希算法。另外mysql_native_password发送的是密码哈希而非进行更安全的质询-响应握手容易受到中间人攻击。caching_sha2_password则完全不同。它的全称是caching SHA-2 password authentication会在服务端缓存认证结果对已经认证过的用户连接有更快的响应速度。在握手阶段客户端不会直接发送密码或密码哈希而是通过非对称加密的方式用服务端下发的RSA公钥加密密码传输或者通过TLS安全连接传输这样就大大降低了密码被窃取的风险。对于现代数据库的安全要求来说这个升级是必要的。所以整体来看MySQL 8.0默认切换认证插件是官方在安全性上的战略性选择。对于普通用户来说理解这个背景很重要因为市面上仍然有很多教程在教直接修改my.ini把默认认证插件改回mysql_native_password这在开发环境快速解决问题可以理解但在生产环境盲目降级认证方式其实是在削弱数据库的安全性。后面我会给出优先级不同的几种方案你可以根据自己的场景选择。2. 最主流的解法把用户的认证插件改成mysql_native_password2.1 查看当前用户的认证插件状态先说最常用的解决办法也是网上最多人推荐的通过SQL命令修改指定用户的认证插件把caching_sha2_password改回mysql_native_password。但这个操作有一个前提你需要能进入MySQL命令行。既然Navicat等图形化工具连不上那一般就用命令行客户端连。在MySQL安装目录的bin目录下或者全局配好环境变量的话直接打开终端/命令提示符执行mysql -u root -p输入密码后进入MySQL命令行界面。第一步是确认当前用户到底使用的什么认证插件SELECT user, host, plugin FROM mysql.user WHERE user root;执行结果类似这样---------------------------------------- | user | host | plugin | ---------------------------------------- | root | localhost | caching_sha2_password | ----------------------------------------看到caching_sha2_password就可以坐实1251报错的原因了。你也可以通过下面这条命令查看当前全局默认的认证插件SHOW VARIABLES LIKE default_authentication_plugin;在MySQL 8.0中结果基本都是caching_sha2_password。如果你用的是MySQL 5.7及更早版本默认值是mysql_native_password这也是为什么老项目在旧版本上跑得好好的一换8.0就突然连不上的原因。2.2 执行ALTER USER修改认证插件确认了插件类型后修改指定用户认证插件的核心命令如下ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的密码; FLUSH PRIVILEGES;这条命令的含义是把root用户在localhost主机下的认证方式改成mysql_native_password同时重新设置密码。这里有几个重要细节需要提醒rootlocalhost是用户和主机地址的组合不要只写用户名。MySQL的账号体系是用户名主机双重身份rootlocalhost和root%是两条完全不同的记录。如果你平时是通过远程IP连接数据库比如用服务器公网地址连可能还要改root%这条记录。不确定有哪些记录的话可以先执行SELECT user, host, plugin FROM mysql.user;查看所有用户及对应主机。IDENTIFIED WITH mysql_native_password BY 你的密码这个语法比较关键WITH指定的就是认证插件类型后面跟BY重新设置密码。如果你只想改插件不想改密码实际上MySQL也支持IDENTIFIED WITH mysql_native_password不带BY的写法但不同小版本兼容性略有差异最稳妥的还是把BY 你的密码带上密码还是用原来的就行。FLUSH PRIVILEGES是刷新权限表让修改立即生效。在MySQL 8.0里执行ALTER USER本身就会立刻生效不需要FLUSH PRIVILEGES重新加载权限但习惯性执行一下也无妨不会造成任何负面影响。修改完成后再用Navicat或之前的客户端重新连接通常就能顺利进入数据库了。2.3 全局/新建用户如何统一处理上面这种方式只对已经存在的用户生效如果你后面新建用户默认还是使用caching_sha2_password到时候还是一个一个改很麻烦。为了避免这种逐个修改的重复劳动可以在MySQL配置文件中修改全局默认认证插件。打开MySQL的配置文件Linux环境下通常在/etc/my.cnf或/etc/mysql/mysql.conf.d/mysqld.cnfWindows环境下是C:\ProgramData\MySQL\MySQL Server 8.0\my.ini在[mysqld]段落下面添加[mysqld] default_authentication_pluginmysql_native_password然后重启MySQL服务新创建的用户就会自动使用mysql_native_password认证不会再出现1251报错。不过这里要再次强调我的建议这种全局降级方式适合开发环境、测试环境或者团队协作时很多老同事都还在用老版本客户端实在没办法统一升级的情况。在正式生产环境如果你对安全性有要求还是优先想办法升级客户端工具而不是把数据库的默认认证方式降回去。把数据库的安全标准降低去迁就客户端总归是治标不治本。3. 长效解法升级客户端工具与驱动3.1 界面工具怎么选第二种思路是反过来不折腾数据库而是把客户端升级到支持caching_sha2_password的版本。这是我个人更推荐的长期方案因为随着MySQL 8.0普及率越来越高很多现代客户端老早就完成适配了。先看图形化客户端工具。如果你用的是Navicat需要确认版本。Navicat 11及更早版本包括网上流传的一些绿色版、精简版基本都不支持MySQL 8.0的caching_sha2_password认证。Navicat 12以上的版本才在MySQL 8.0兼容性上做了完善支持Navicat 16、17更是全面适配。如果你用的版本比较老优先升级客户端比改数据库插件更省心。MySQL Workbench是官方出品的图形化管理工具从8.0.11以后的版本就可以完整支持caching_sha2_password认证如果发现连不上升级到最新版即可解决。另外DBeaver、DataGrip、TablePlus这些主流工具对新认证协议支持都比较到位基本开箱即用。这里补充一个经验连接MySQL 8.0时如果用的工具比较新但还是报1251先不急着改插件可以在工具的连接配置里找找服务器身份验证或认证方式相关的选项。比如JDBC连接串中可以显式指定使用caching_sha2_password。3.2 编程语言连接串怎么调说了图形工具编程语言连接MySQL的场景也很常见而且不少项目遇到1251根本不是界面工具的问题而是项目里的数据库连接代码报错。Python开发者使用PyMySQL连接MySQL 8.0时如果版本较旧就会报1251错误。解决办法很简单升级PyMySQL到1.0.0以上版本pip install --upgrade pymysql连接时使用新版驱动底层会自动处理认证协议协商不再需要手动干预。Java后端项目使用JDBC驱动连接MySQL 8.0时要注意驱动包版本。MySQL Connector/J的8.0版本驱动已经支持caching_sha2_password认证协议但如果你的项目中使用的是5.1.x老版本驱动连接8.0数据库时就会报错。解决方案是在pom.xml或gradle中升级驱动依赖。Maven项目示例dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependency升级驱动后需要在JDBC连接串里指定时区等参数才能正常连接jdbc:mysql://localhost:3306/dbname?useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue这里补充一个非常重要的知识点。如果客户端驱动支持caching_sha2_password但是在非SSL连接下首次连接时客户端需要从服务端获取RSA公钥来加密密码传输。这时候如果连接串没有设置allowPublicKeyRetrievaltrue很多驱动会报错提示公钥检索被禁用。这个报错虽然不是1251但也和认证协议相关容易让人混淆。我建议在使用MySQL 8.0和较新驱动时开发环境连接串中加上allowPublicKeyRetrievaltrue同时把useSSLfalse这样能减少很多奇怪的身份验证问题。生产环境则建议配置SSL连接。PHP项目使用mysqli扩展或PDO扩展时也需要注意版本。PHP 7.4以上配合mysqlnd驱动对MySQL 8.0的新认证支持已经比较完善。如果你用的是老旧的PHP版本那可能就是需要升级运行环境或者走修改认证插件方案。表格总结一下不同客户端的解决方案客户端/驱动推荐版本关键操作Navicat12及以上升级到新版无需修改数据库MySQL Workbench8.0.11升级到最新版DBeaver22.x直接连接即可PyMySQL1.0.0pip install --upgrade pymysqlmysql-connector-java8.0.x升级Maven依赖PHP mysqlndPHP 7.4升级PHP版本4. 报错并非只有1251这些相关异常要分清4.1 容易混淆的“Authentication plugin cannot be loaded”你在使用MySQL 8.0时除了1251还有可能遇到另一个非常相似的报错Authentication plugin caching_sha2_password cannot be loaded这个报错和1251的区别在哪里呢1251是客户端不支持服务端的认证协议而Authentication plugin cannot be loaded是客户端干脆不认识这个认证插件在加载插件阶段就失败了。区分两者的关键在于报错文本。1251强调的是does not support authentication protocol意思是我知道你用的什么认证方式但我支持不了cannot be loaded则是我根本认不出你用的认证插件。前者往往出现在连接阶段失败后者在初始化认证阶段就中断。当然这两个错误经常同时出现在同一个客户端版本上排查思路基本一致要么升级客户端要么把服务端用户的认证插件改成老的mysql_native_password。有时候还会出现Caching_sha2_password requires secure connection and RSA public key retrieval这个问题的背景是caching_sha2_password插件在某些场景下需要TLS/SSL加密连接或者需要客户端允许从服务器获取RSA公钥来加密密码传输。如果你使用的客户端工具或连接驱动器默认安全设置过严没有允许公钥检索就会报这个错。在连接参数里加上allowPublicKeyRetrievaltrue或者启用SSL连接通常就能解决。举个例子使用Python的mysql-connector-python连接时如果出现上面这个报错可以在连接时明确开启公钥获取conn mysql.connector.connect( hostlocalhost, userroot, passwordyourpassword, databasetestdb, allow_public_key_retrievalTrue, use_pureTrue )如果还是不放心可以进一步强制SSL连接ssl_disabledFalse并配置CA证书路径。但在本地开发环境中allowPublicKeyRetrievaltrue配合useSSLfalse基本够用。4.2 另一个常见场景远程连接被拒绝很多时候你把1251搞定之后连接时又冒出另一个错误Host x.x.x.x is not allowed to connect to this MySQL server这是MySQL权限体系里的访问控制问题。MySQL用户的账号不仅仅有用户名还绑定了允许连接的主机地址。默认安装的MySQLroot用户只允许从localhost本机连接如果你拿着服务器的账号从局域网其他电脑远程连肯定被拒绝。解决方法是创建一个允许指定IP或任意IP访问的用户比如CREATE USER mysqluser% IDENTIFIED BY mypassword; GRANT ALL PRIVILEGES ON *.* TO mysqluser% WITH GRANT OPTION; FLUSH PRIVILEGES;这里%表示允许任何主机连接。如果你只想让某台固定IP的机器访问就把%换成具体IP。实际项目中建议只给特定IP赋予权限不要图方便全部用%否则数据库暴露在公网上会引来大量暴力破解尝试。4.3 密码加密规则冲突导致的“无法加载”另一个潜在问题是如果你从MySQL 5.7或更早版本迁移数据到8.0老用户是mysql_native_password加密存储的8.0系统虽然兼容读取老插件但如果迁移时密码哈希数据损坏或不兼容也有可能出现奇怪的认证报错。遇到这种情况简单办法就是重新设置一下密码ALTER USER rootlocalhost IDENTIFIED BY 新密码;这个操作会让MySQL用当前默认插件重新生成密码哈希通常会解决密码哈希与新插件版本不匹配的异常情况。从排查角度来说1251这个报错能延伸出很多相关问题原因是认证协议这个东西本来就比较底层。我把常见的关联报错整理成一个速查表方便你对照处理报错关键词根本原因快速处理Client does not support authentication protocol (1251)客户端版本太老不认识/不支持新认证插件升级客户端或ALTER USER改用mysql_native_passwordAuthentication plugin cannot be loaded客户端驱动不认识caching_sha2_password插件升级驱动版本或修改用户插件Caching_sha2_password requires secure connection非SSL连接下需要获取RSA公钥但被禁用加allowPublicKeyRetrievaltrueHost is not allowed to connect用户host限制不匹配当前来源IP创建user%或指定IP的用户Access denied for user密码错误或权限不足检查密码GRANT授权5. 实测排查流程与避坑要点5.1 一套完整的排查步骤如果你现在正被1251困扰不知道怎么选择解决方案完全可以照着下面的顺序一步步来第一步先用命令行客户端测试连接确认服务端本身没问题mysql -u root -p -h localhost如果命令行能连进去说明数据库服务端和应用端口都是正常的问题100%出在客户端工具或驱动上。第二步查询用户认证插件类型。SELECT user, host, plugin FROM mysql.user WHERE user root;确认root用户用的是什么插件。这一步是判断后续操作方案的关键依据。第三步根据实际情况选择处理路径。如果你是个人开发电脑连接本地数据库用Navicat等图形工具那就先考虑升级工具版本这是最省心最安全的方式。如果你用的是公司提供的老虚拟机镜像客户端版本已经固化没法升级那就退而求其次执行ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的密码; FLUSH PRIVILEGES;第四步修改后立刻用之前的客户端重新连接测试正常情况下问题就能解决。如果连接还是失败则再检查端口、防火墙、bind_address等配置因为这些因素也会导致连接失败有时报错信息会被统一合并成1251取决于客户端工具的具体实现。在Linux服务器上排查端口监听时可以使用netstat -tlnp | grep 3306 ss -tlnp | grep 3306确认mysqld进程监听的是0.0.0.0还是127.0.0.1如果是127.0.0.1则远程连接不可能成功需要修改my.cnf中的bind_address[mysqld] bind_address0.0.0.05.2 避坑要点修改认证插件后的连带影响修改认证插件这个方法虽然简单直接但有几个连带影响需要注意。第一如果你是升级了客户端之后仍然使用mysql_native_password老插件建议在合适的时间窗口将认证方式重新切回caching_sha2_password。长期使用老认证方式在8.0上虽然兼容但不推荐作为生产环境的长期配置。第二修改认证插件后如果是项目代码里使用的账号记得同步检查代码里是否有使用加盐哈希或其他针对mysql_native_password定制的特殊认证逻辑。这种定制代码在老插件上能跑换到新插件上可能会出错。第三执行ALTER USER修改密码时如果数据库有主从复制架构需要特别注意因为主库修改了用户的认证插件和密码哈希从库的复制关系可能不会自动同步这种变更。在这种架构下需要在所有相关节点上都执行相应的修改或者使用CHANGE REPLICATION FILTER语法把mysql系统库排除在复制范围之外否则可能导致复制线程报错。这属于比较高级的运维场景一般单机开发环境碰不到但如果你是在公司团队里升MySQL版本建议提前评估清楚。5.3 一些更稳妥的服务端调整策略除了上面讲的直接修改root用户我更建议你在日常开发中养成创建专用账号的习惯。不要所有项目都一股脑用root连接数据库这样权限太宽容易误操作而且root的认证插件设置会影响整个数据库实例一旦切换所有使用root的客户端都会受到影响。比如创建一个新的开发者账号只赋给某个库的权限CREATE USER devlocalhost IDENTIFIED WITH mysql_native_password BY devpassword; GRANT ALL PRIVILEGES ON myapp_db.* TO devlocalhost; FLUSH PRIVILEGES;这样即使后续需要调整认证方式影响的也只是这个开发账号不会波及root以及其他高权限用户。生产环境的数据库账号我强烈建议采用最小权限原则并且不要在多个服务之间共用同一个账号。另外如果你管理的是已有线上业务不能随便重启MySQL服务那修改全局配置文件的方案就要格外谨慎。因为修改default_authentication_plugin之后需要重启MySQL服务才能生效重启会造成业务中断。这种情况下ALTER USER这种方式不要求重启服务反而更友好可以在线执行几乎不影响正在运行的业务。6. 真实案例模拟从报错到连接成功为了帮你把上面的内容串起来我模拟一个非常典型的真实场景从头到尾过一遍。假设某个开发者的机器上装了MySQL 8.0.33用Navicat 11连接本机数据库连接时弹出1251报错。他按照网上教程一顿操作把密码改了又改发现没用。然后他找到了这篇文章按如下流程处理。第一步打开系统环境变量把MySQL的bin目录配置到PATH里。Windows下一般是C:\Program Files\MySQL\MySQL Server 8.0\bin。第二步打开命令提示符执行mysql -u root -p输入密码进入命令行。执行SELECT user, host, plugin FROM mysql.user;看到root用户plugin为caching_sha2_password。第三步因为他的Navicat 11版本太老不想升级可能是公司采购的授权版本升级需要申请预算于是采用ALTER USER方案ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 原来的密码; FLUSH PRIVILEGES;执行后没有任何报错。第四步重新打开Navicat 11连接输入密码这次成功连上数据库列表正常展示。这个案例是典型的“老客户端 新服务端”兼容性问题。如果同样的情况下你用了Navicat 16大概率就不会遇到1251。所以也再次提醒这个报错不是密码问题不是权限问题就是客户端与服务端认证协议不匹配。如果案例换成编程语言场景比如Spring Boot项目里项目用的是mysql-connector-java 5.1.47连MySQL 8.0Tomcat启动时数据源初始化报错日志里有Client does not support authentication protocol requested by server。那就在pom.xml里把依赖升级到8.0.33然后改一下连接串jdbc:mysql://localhost:3306/testdb?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalseallowPublicKeyRetrievaltrue重启应用数据源初始化成功。这也是非常典型的生产环境修复场景。7. 从问题出发的一些延伸建议到这里1251报错的来龙去脉、解决方案和排查流程就已经讲完了。我个人实际处理过很多次这个问题最深的体会是碰到数据库连接类报错不要第一时间怀疑密码和权限先分析协议和版本兼容性。很多新手在1251上报错后反复重置密码、重启服务、卸载重装费了大量时间却没有效果就是因为没有理解Linux客户端和服务端在认证层面的沟通机制。我的建议是日常开发中把客户端工具、编程语言驱动和MySQL服务端的版本关系梳理清楚。官方文档里明确列出了各版本驱动与服务器认证插件的兼容性矩阵遇到问题时先查这个矩阵比自己瞎试高效得多。同时无论你最终选择了升级客户端还是修改认证插件都要在自己本地记录一下当时操作的环境版本比如MySQL 8.0.33、Navicat 15、mysql-connector-java 8.0.33等下次换电脑、换团队再遇到类似问题翻一下记录就知道该怎么处理。最后再分享一个小技巧如果你不想修改root用户的认证插件也暂时不想升级Navicat可以考虑在Navicat的连接设置里手动指定使用旧版mysql_native_password插件具体入口在连接的高级选项中不同Navicat版本略有差异有些版本叫“使用旧版本认证协议”。但要注意这个选项能让老客户端继续连接新服务端但前提是服务端允许该插件存在。如果服务端已经禁用了mysql_native_password这个选项也不会生效。总体而言在MySQL 8.0上直接修改默认认证插件或者升级客户端驱动仍是通行的最佳实践。
返回列表