MySQL 8.0 - 客户端不支持服务器请求的身份验证协议;考虑升级MySQL客户端。

755

由于某些原因,我无法与服务器建立简单的连接。我使用默认设置安装了最新的MySQL Community 8.0数据库以及Node.JS。

这是我的Node.js代码

    var mysql = require('mysql');
    
    var con = mysql.createConnection({
      host: "localhost",
      user: "root",
      password: "password",
      insecureAuth : true
    });
    
    con.connect(function(err) {
      if (err) throw err;
      console.log("Connected!");
    });

以下是在命令提示符中发现的错误:

C:\Users\mysql-test>node app.js
    C:\Users\mysql-test\node_modules\mysql\lib\protocol\Parse
    r.js:80
            throw err; // Rethrow non-MySQL errors
            ^
    
Error: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client
    at Handshake.Sequence._packetToError (C:\Users\mysql-
test\node_modules\mysql\lib\protocol\sequences\Sequence.js:52:14)
    at Handshake.ErrorPacket (C:\Users\mysql-test\node_mo
dules\mysql\lib\protocol\sequences\Handshake.js:130:18)
    at Protocol._parsePacket (C:\Users\mysql-test\node_mo
dules\mysql\lib\protocol\Protocol.js:279:23)
    at Parser.write (C:\Users\mysql-test\node_modules\mys
ql\lib\protocol\Parser.js:76:12)
    at Protocol.write (C:\Users\mysql-test\node_modules\m
ysql\lib\protocol\Protocol.js:39:16)
    at Socket.<anonymous> (C:\Users\mysql-test\node_modul
es\mysql\lib\Connection.js:103:28)
    at Socket.emit (events.js:159:13)
    at addChunk (_stream_readable.js:265:12)
    at readableAddChunk (_stream_readable.js:252:11)
    at Socket.Readable.push (_stream_readable.js:209:10)
    --------------------
    at Protocol._enqueue (C:\Users\mysql-test\node_module
s\mysql\lib\protocol\Protocol.js:145:48)
    at Protocol.handshake (C:\Users\mysql-test\node_modul
es\mysql\lib\protocol\Protocol.js:52:23)
    at Connection.connect (C:\Users\mysql-test\node_modul
es\mysql\lib\Connection.js:130:18)
    at Object.<anonymous> (C:\Users\mysql-test\server.js:
11:5)
at Module._compile (module.js:660:30)
at Object.Module._extensions..js (module.js:671:10)
at Module.load (module.js:573:32)
at tryModuleLoad (module.js:513:12)
at Function.Module._load (module.js:505:3)
at Function.Module.runMain (module.js:701:10)

我已经阅读了一些内容,例如: https://dev.mysql.com/doc/refman/5.5/en/old-client.html https://github.com/mysqljs/mysql/issues/1507

但是我仍然不确定如何解决我的问题。


11
所有使用 SQLTools 扩展程序的 VS Code 用户,如果在使用过程中遇到问题,特别是在您刚刚升级了开发计算机上的 MySQL 实例时,请参考本文章。请注意,这篇文章旨在帮助您解决问题,因此请勿更改原文意思。 - OzzyTheGiant
我曾经遇到过相同的问题,因为我在连接时使用了3306端口,但是当我安装MySQL时,我将默认端口设置为了3307。所以请注意,这也可能是协议不匹配引起的。 - Stepan Rafael
你应该考虑将被接受的答案更改为Aidin的。 - Mike
MySQL 8版本目前尚未被Strapi支持。不过,官方博客文章提供了帮助您配置MySQL 8与Strapi的方法。请访问官方博客文章获取更多信息。 - Rubek Joshi
1
只需将您的npm包更新为mysql2 链接。更多详细信息请参见 SO答案。 - Lorraine R.
35个回答

1832

在 MYSQL Workbench 中执行以下查询:

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';

其中root是你的用户名,localhost是你的 URL,password 是你的密码。

然后运行此查询以刷新权限:

flush privileges;

之后尝试使用 Node 进行连接。

如果不起作用,请尝试不包含 @'localhost' 部分。


36
在没有使用"@localhost"的情况下,对我来说这个方法可行(我猜是因为它不适用于root用户)。 - NicolasZ
20
如果您知道根密码,请用您的根密码替换'password'。 - Vedha Peri
31
它现在可以运行了......但为什么之前不能运行,以及为什么在这个查询之后它能够运行仍然是一个问题。 - saksham
8
大家好!有人能深入解释一下这里发生了什么吗?为什么更改本地用户会使这种错误消失? - Guilherme Matuella
31
你好 @GuilhermeMatuella,这是因为MySQL 8.0引入了caching_sha2_password,但是Node.js版本尚未实现。 - Daksh Gargas
显示剩余21条评论

728

摘要

  1. 如果你只是想消除错误,但愿意冒项目安全风险的代价(例如这只是个个人项目或开发环境),请参考@Pras's answer -- ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password',然后执行flush privileges
  2. 如果你想修复它,却不知道为什么,只需安装并使用mysql2(而不是mysql)-- npm i mysql2,然后使用mysql = require('mysql2');
  3. 如果你是一个好奇的开发者,总是渴望学习,请继续阅读... :)

发生了什么?

首先让我们搞清楚发生了什么。

MySQL 8支持可插拔的身份验证方法。默认情况下,其中之一名为caching_sha2_password的方法被使用,而不是我们好久以前用的mysql_native_password(source)。显然,使用带有几次握手的加密算法比已存在24年的纯密码传递更安全!

现在的问题是,在Node中mysqljs(通过npm i mysql安装并在您的Node代码中使用的包)尚未支持MySQL 8的这种新默认身份验证方法。该问题在此处:https://github.com/mysqljs/mysql/issues/1507,截至2019年7月,它仍然保持打开状态已经有3年了。

2019年6月更新:现在有一个mysqljs的新PR来解决这个问题!

2020年2月更新:显然,它计划在mysqljs的第3个版本中推出

2020年7月更新: 显然到目前为止(至少截至2020年4月),它仍未出现,但声称 node-mysql2 支持身份验证切换请求。如果node-mysql2可以解决这个问题,请在下面发表评论--我将自己测试。

2021年4月更新:看起来问题仍然存在,就在3天前,有人创建了一个分支并将其放在那里 - 但尚未成为mysql.js包的官方版本。 此外,根据下面的评论,mysql2软件包运行良好,并且正确支持身份验证开关


您现在的选择

选项一) [不建议] 将"MySQL"降级以使用老旧的"mysql_native_password"进行身份验证

这是大家都建议的方法(例如上面的最佳答案)。您只需进入mysql并运行一个查询,说root可以使用旧的mysql_native_password方法进行身份验证:

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password ...

好消息是,生活将变得简单,您仍然可以使用 Sequel Pro 等老工具而不会出现 任何问题。但问题在于,您没有利用可用的更安全(并且很酷,请参见下文)资源。

选项2) [呃……] 使用 MySQL Connecter X DevAPI 替换 "Node" 包

MySQL X DevAPI for Node 是由 http://dev.mysql.com 官方团队提供的 Node's Mysqljs package 的替代品。

它完美地支持 caching_sha2_password 认证。 (只需确保您使用端口 33060 进行X 协议通信。)

不好的消息是,您已经离开了我们大家都习惯和依赖的旧版mysql软件包。

好消息是,现在您的应用程序更加安全,并且您可以利用一堆新功能,这些功能我们以前的老朋友们并没有提供!只需查看X DevAPI教程,您就会发现它有许多新的性感功能,这些功能可能会派上用场。您只需要付出学习曲线的代价,这是任何技术升级都会有的预期结果。:)

PS. 不幸的是,此XDevAPI软件包尚未具备类型定义(TypeScript可理解),因此如果您使用TypeScript,则会遇到问题。我尝试使用dts-gendtsmake生成.d.ts文件,但无法成功。所以请注意。

选项3)[推荐]使用"mysql2.js"软件包替换"mysql.js"

如上所述,mysql包(NPM包链接)在2021年4月仍然存在这个问题。但是mysql2包(NPM包链接)没有这个问题。因此,以下可能是一行答案!

npm un mysql && npm i mysql2

请注意,mysql2 是基于流行的mysql进行的分支工作,但其受欢迎程度(2020年4月每周有620K次下载量的mysql2)已经接近原始软件包(2021年4月每周有720K次下载量的mysql),因此切换似乎是合理的!

71
很好,一个真正解释mysql_native_password的答案,而不仅仅是告诉你去做。 - wizloc
6
好的,一次恰当的解释。Aidin做得很好。但我希望连接应用程序不要自动配置端口3306到MySQL。我们已经有足够的麻烦将MySQL和MariaDB从3306端口中剥离出来了。 - Trunk
2
@emen,如果你不喜欢阅读库代码(而不是适当的文档),或者需要引入TypeScript,或者安全对于你的项目来说不是一个威胁生命的问题,那么不,不要选择选项#2。 :) - Aidin
2
感谢您提供的详细信息,@Henrique。是的,这不应该是一个答案,除非您认为StackOverflow上的回答就像这样:https://pics.me.me/my-eyes-on-stackoverflow-17-it-as-getlientokens-nosuch-refresh-token-1-then-function-tokens-61976976.png ;) - Aidin
13
mysql2 很优雅地解决了这个问题。我认为这是最适当的解决方案。 - Stalinko
显示剩余23条评论

114

使用旧的mysql_native_password是可行的:

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'YourRootPassword';
-- or
CREATE USER 'foo'@'%' IDENTIFIED WITH mysql_native_password BY 'bar';
-- then
FLUSH PRIVILEGES;

这是因为MySQL 8.0引入了caching_sha2_password,但Node.js版本尚未实现。您可以查看此拉取请求此问题以获取更多信息。可能很快就会有一个修复!


1
添加 @localhost 和仅使用 'root' 有什么区别? - filemonczyk
1
查询可以正常工作。但是节点仍然无法连接到MySQL服务器。有任何想法吗?以下是错误信息:{ "code": "ER_ACCESS_DENIED_ERROR", "errno": 1045, "sqlMessage": "Access denied for user 'root'@'localhost' (using password: YES)", "sqlState": "28000", "fatal": true } - Sanjay Pradeep

51

MySQL 8的完整步骤

连接到MySQL

$ mysql -u root -p
Enter password: (enter your root password)

重置您的密码

(将your_new_password替换为您想要使用的密码)

mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_new_password';
mysql> FLUSH PRIVILEGES;
mysql> quit

然后尝试使用节点进行连接


@sky,请查看我上面的答案以获取详细信息。 - Aidin
我更喜欢这种直接的方法,而不是在混乱的Mysql Workbench中游荡,不知道命令是否真正运行。 - Kalnode
这个解决方案对我有效,但是没有使用@'localhost'。 - Jimmy Shaw

26

虽然被认可的答案是正确的,但我更喜欢创建一个新用户,然后使用该用户访问数据库。

create user nodeuser@localhost identified by 'nodeuser@1234';
grant all privileges on node.* to nodeuser@localhost;
ALTER USER 'nodeuser'@localhost IDENTIFIED WITH mysql_native_password BY 'nodeuser@1234';

2
如果有人想要这样做,这里有一篇文章提供了一些解释:https://www.digitalocean.com/community/tutorials/how-to-create-a-new-user-and-grant-permissions-in-mysql - Devin
Siddhant可能“更喜欢”,但我“必须”这样做。在我看来,这使得这个答案成为必读! - Parapluie
对我来说,给定的权限不足以创建数据库。我使用了 grant all privileges on *.* to nodeuser@localhost; - Shubham Shaw
我认为在这里使用授权权限对我很有效。我可以建议别人使用这个答案。 - Ezrqn Kemboi
2
那个“nodeuser@1234”到底是什么?一个新密码吗?我们为什么需要它? - sander
@sander 我刚刚清理了代码,使其更易于理解(如果它被批准的话):CREATE USER 'nodeuser'@'localhost' IDENTIFIED WITH mysql_native_password BY 'somePassword'; GRANT ALL PRIVILEGES ON node.* TO 'nodeuser'@'localhost'; - Jacopo Pace

26

如果您遇到此问题,但仍然希望使用版本8的MySQL,您可以这样做。在使用Docker创建数据库时,您可以通过指示MySQL服务器实施传统认证插件来实现这一点。

因此,您的compose文件将如下所示:

# Use root/example as user/password credentials

version: '3.1'

services:

  db:
    image: mysql:8.0.15
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
       MYSQL_ROOT_PASSWORD: 'pass'
       MYSQL_DATABASE: 'db'
       MYSQL_USER: 'user'
       MYSQL_PASSWORD: 'pass'
    ports:
      - 3318:3306
    # Change this to your local path
    volumes:
      - ~/Database/ORM_Test:/var/lib/mysql

2
我正在使用这个 command,但是在 Node.js 中使用 mysql 时仍然收到不支持的身份验证错误消息。 - Juha Untinen
完整的堆栈跟踪在这里:https://pastebin.com/SzayQzdh,**docker-compose.yml**:https://pastebin.com/7pUrWYDs。错误本身是:“Error:ER_NOT_SUPPORTED_AUTH_MODE:客户端不支持服务器请求的认证协议,请考虑升级MySQL客户端”。 - Juha Untinen
3
请确保你删除了 Docker 容器(由 docker-compose 创建的容器)和卷(~/Database/ORM_Test),然后再次运行 'docker-compose up'。否则,来自 'command' 的更改将不会生效。这在我的情况下有帮助。 - Vitalii Ivanov
命令必须在创建用户之前在docker-compose中设置。如果您正在使用MYSQL_USER和MYSQL_PASSWORD,则必须清除/var/lib/mysql并从头开始设置命令,然后再创建用户,或者退回到其他答案之一,并更改已经创建的用户。 - CompEng88
@VitaliiIvanov 没错。可以通过 docker-compose down --volumes && docker-compose up 来实现。 - nalzok

22

最简单的答案是:

  1. 在Node中使用mysql2而不是mysql

在Node中安装mysql2

  1. npm install mysql2

不要降级你的mysql数据库。

你已经准备好了。 Happy Coding!


不要忘记在 require 中更改为 mysql2。 - Heesu Kim
我得到的结果是[object Object],[object Object][object Object].... 这是什么原因引起的? - Syrus
找到了解决方案。它检索对象,因此我必须按行和列读取它。 - Syrus

20

如果 ALTER USER ... 命令行无法使用,并且你正在使用 Windows 10,则尝试按照以下步骤操作:

1)在Windows搜索栏中键入MySQL

2)打开 MySQL Windows Installer - Community

3)查找“MySQL服务器”,然后单击重新配置 step 3

4)单击“下一步”直到达到“身份验证方法”阶段

5)在“身份验证方法”阶段,选中第二个选项“使用传统身份验证方法” step 5

6)然后按照 Windows 安装程序给出的步骤一直进行到结束

7)完成后,从Windows搜索栏进入“服务”,单击“启动” MySql81。

现在,再试一次,MySQL和Node.js之间的连接应该可以工作了!


这个解决方案解决了我的问题。我的代码没问题,只是我的 Windows 10 认证有问题。 - Donald W Garton

14

在最新的Mysql Docker容器中

ALTER USER root IDENTIFIED WITH mysql_native_password BY 'password';

2
警告:这将使您的数据库变得不太安全。 - Will Sheppard

14
最简单的解决方案是执行以下命令,这个问题就会消失:
npm uninstall mysql
npm install mysql2

然后在您的代码中正常使用它:

var mysql = require('mysql2');
    
var con = mysql.createConnection({
 host: "localhost",
 user: "root",
 password: "password"
});
    
con.connect(function(err) {
 if (err) throw err;
 console.log("Connected!");
});

我的系统中没有任何MySQL客户端,但是我的docker容器有一个镜像,导致了这个问题。只需安装mysql2即可解决问题。

您也可以在官方mysql npm包问题答案中这里找到解决方案。祝一切顺利。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接