这是客户端与mysql 8.0服务器认证协议不兼容所致:服务器默认用caching_sha2_password,而旧版navicat、php mysqli、node.js mysql等客户端仅支持mysql_native_password,导致连接在握手阶段失败,报错er_not_supported_auth_mode或“client does not support authentication protocol”。

直接结论:这不是权限配置错了,而是客户端和服务器在“握手”阶段就卡在认证协议上——MySQL 8.0 默认用 caching_sha2_password,而你的客户端(PHP、Node.js、Navicat、Unity 等)还在认 mysql_native_password。
确认是不是认证协议问题
别急着改配置,先验证错误是否真源于此。连接失败时,典型报错是:ER_NOT_SUPPORTED_AUTH_MODE 或 Client does not support authentication protocol requested by server。
登录 MySQL(用 root 或有权限账号),执行:
SELECT User, Host, plugin FROM mysql.user WHERE User = 'your_username';
如果返回的 plugin 是 caching_sha2_password,而你用的是旧版 Navicat 12、PHP 7.x 的 mysqli、Node.js 的 mysql 包(非 mysql2),那基本就是它了。
- 注意:
SHOW GRANTS正常 ≠ 认证成功——权限语句能查出来,但连接根本进不来 - 5.7 升级到 8.0 后未运行
mysqld --upgrade,也可能导致mysql.user表字段不全,间接让插件字段读取异常
临时修复:ALTER USER 切换认证插件
这是最快见效、无需重启服务的方法,适合开发/测试环境快速验证。
在 MySQL 命令行中执行(把 your_username 和 your_password 换成真实值):
ALTER USER 'your_username'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password';<br>FLUSH PRIVILEGES;
- 若要允许远程连接,把
'localhost'改成'%'或具体 IP,如'192.168.1.100' - 修改后务必执行
FLUSH PRIVILEGES;,否则不会生效 - 该操作只影响指定用户,不影响其他用户或全局默认设置
- 不推荐长期用于生产环境——
mysql_native_password安全性弱于caching_sha2_password
长期方案:升级客户端驱动或显式启用新协议
治本的方式不是降级服务器,而是让客户端跟上节奏。
不同语言/工具的适配要点:
- PHP:用
PDO时加选项PDO::MYSQL_ATTR_SSL_CA不管用;关键是确保 PHP 版本 ≥ 7.4 且mysqli扩展已更新;更稳妥是改用mysqlnd驱动并确认支持 sha2 - Node.js:弃用
mysql包,改用mysql2(原生支持caching_sha2_password) - Java(JDBC):用
mysql-connector-java≥ 8.0.11,并在连接 URL 中加参数?serverTimezone=UTC&allowPublicKeyRetrieval=true&useSSL=false - Navicat:升级到 15+ 版本;老版本即使填对密码也连不上,没得绕
如果你用的是 Unity + MySQL.Data.dll,必须换新版 DLL(≥ 8.0.23),旧版 DLL 会硬编码拒绝 caching_sha2_password 握手。
别踩的坑:全局改 default_authentication_plugin
有人想一劳永逸,在 my.cnf 里加:
[mysqld]<br>default_authentication_plugin=mysql_native_password
这会导致所有新建用户都用旧协议,看似省事,实则埋雷:
- 重启 MySQL 才生效,线上服务可能中断
- 新用户自动失去更安全的认证能力,违背 MySQL 8.0 的安全设计初衷
- 某些中间件(如 ProxySQL、MaxScale)依赖新协议特性,改了反而引发新兼容问题
- 如果后续又装了需要新协议的组件(比如新版监控 agent),还得再调回来
真正容易被忽略的点是:**协议不匹配 ≠ 权限没给够,它发生在鉴权之前,连用户是谁都还没确认**。所以排查时不要陷在 GRANT 语句里打转,先看 plugin 字段和客户端能力清单。











