无法使用旧的身份验证方法连接MySQL 4.1+。

69

我正在尝试连接到http://bluesql.net的MySQL数据库,但是当我尝试连接时,它出现了以下错误:

Connect Error (2000) mysqlnd cannot connect to MySQL 4.1+ using old authentication

我研究了一下,这与MySQL 4.1之前使用的一些旧密码方案有关。较新版本有使用旧密码的选项,我读到可能会引起这个问题。

我正在运行php 5.3,并使用mySQLi (new mysqli(...)) 进行连接。我希望我能在代码中做些什么,以连接到 bluesql.net 上的数据库-很明显,我无法控制他们的数据库设置。降低php版本不是一个选项。

有人有任何想法吗?


3
@Hill 很抱歉你有这种感受 :( 。但如果没有开源,我们基本上仍然生活在穴居人时代。除了我的项目外,没有一个开源项目是完美的;但在很多情况下,开源软件库比封闭源代码的东西更值得信赖。当然,在最终用户软件的情况下是不同的。 - B T
7个回答

73

编辑:仅当您控制MySQL服务器时才适用...如果您没有控制,可以查看Mysql密码哈希方法旧与新

首先使用SQL查询进行检查

SHOW VARIABLES LIKE 'old_passwords'

无论你使用MySQL命令行客户端,HeidiSQL或其他你所喜欢的前端工具,在这些工具中都可以检查服务器是否默认使用旧密码架构。如果返回结果为old_passwords,Off,则用户表中可能存在旧密码记录。MySQL服务器将为这些帐户使用旧的身份验证程序。你只需为该帐户设置一个新密码,就会使用新的程序。

你可以通过查看mysql.user表(使用有访问权限的账户)来确定将使用哪种程序。

SELECT `User`, `Host`, Length(`Password`) FROM mysql.user

对于使用旧密码的账户,这将返回16,对于使用新密码的账户,它将返回41(对于完全没有密码的帐户,它将返回0,您可能也需要处理这些情况)。
要么使用MySQL前端的用户管理工具(如果有的话),要么

SET PASSWORD FOR 'User'@'Host'=PASSWORD('yourpassword');
FLUSH Privileges;

(用前一个查询得到的值替代UserHost。) 然后再次检查密码长度,现在应该是41,你的客户端(例如mysqlnd)应该能够连接到服务器。

另请参阅MySQL文档: * http://dev.mysql.com/doc/refman/5.0/en/old-client.html
* http://dev.mysql.com/doc/refman/5.0/en/password-hashing.html
* http://dev.mysql.com/doc/refman/5.0/en/set-password.html


1
感谢您提供详细的答案。我已经成功连接了GUI客户端,而且old_passwords确实是“ON”。当我执行“set old_password = OFF”时,我以为问题解决了,但是当我开始新的会话后,它又变成了“ON”。 - B T
哎呀,我没意识到你没有控制服务器(某种潜在的文本盲)。在这种情况下,我认为查尔斯是正确的。或者...也许bluesql.net的并非所有服务器都配置为使用短密码哈希。如果你询问他们,也许可以转移到另一个服务器。 - VolkerK
4
好的回答。我需要执行 SET old_passwords = 0; 才能使它起作用,这个方法来自于下面Elliot Yap的回答。 - homerjam
3
我完成了上述所有步骤,但修改密码后仍然得到16的结果。 - PHP Avenger
在执行SET PASSWORD FOR 'user'@'host' = password('yourpassword');之前,您必须先执行SET old_passwords=0 - Stack Underflow

65

如果你没有服务器控制权

我曾经遇到过这个问题,并且找到了解决方法。

首先,使用一个不介意旧密码的旧客户端连接到MySQL数据库。使用你的脚本将要使用的用户进行连接。

运行以下查询:

SET SESSION old_passwords=FALSE;
SET PASSWORD = PASSWORD('[your password]');

在您的PHP脚本中,将mysql_connect函数更改为包含客户端标志1:

define('CLIENT_LONG_PASSWORD', 1);
mysql_connect('[your server]', '[your username]', '[your password]', false, CLIENT_LONG_PASSWORD);

这使我成功连接了。

编辑:根据Garland Pope的评论,自PHP 5.4起,可能不再需要在您的PHP代码中手动设置CLIENT_LONG_PASSWORD!

编辑:感谢Antonio Bonifati提供的PHP脚本,可为您运行查询:

<?php const DB = [ 'host' => '...', # localhost may not work on some hosting 
    'user' => '...',
    'pwd' => '...', ]; 

if (!mysql_connect(DB['host'], DB['user'], DB['pwd'])) {
    die(mysql_error());
} if (!mysql_query($query = 'SET SESSION old_passwords=FALSE')) {
    die($query);
} if (!mysql_query($query = "SET PASSWORD = PASSWORD('" . DB['pwd'] . "')")) {
    die($query);
}

echo "Excellent, mysqli will now work"; 
?>

3
我只需要执行两个SET语句便修复了我的问题(PHP 5.4,MySQL 5.0)。PHP代码无需更改: $this->dbh = mysql_connect(DB_HOST, DB_USER, DB_PASSWD); - Garland Pope
如果您没有访问用户表的权限,这确实是最佳解决方案。 - Michael
我正在使用mysqli模块(PHP 5.6,MySQL 5.0),并且遇到了相同的问题。我按照您的步骤进行操作,但是我收到了相同的警告:使用phpmyadmin正确执行MySQL查询,但我找不到使用mysqli模块的PHP部分的等效代码。我该怎么办?(如果重要的话,我的网站托管在Aruba的Windows VM上...) 谢谢 :) - gior91
以下是修复问题的 PHP 脚本,无需外部 shell 访问或连接到数据库服务器:<?php
const DB = [ 'host' => '...' # localhost 在某些托管上可能无法使用 'user' => '...', 'pwd' => '...', ];
if (!mysql_connect(DB['host'], DB['user'], DB['pwd'])) { die(mysql_error()); } if (!mysql_query($query = 'SET SESSION old_passwords=FALSE')) { die($query); } if (!mysql_query($query = "SET PASSWORD = PASSWORD('" . DB['pwd'] . "')")) { die($query); }
echo "非常好,mysqli 现在可以工作了"; ?>
- Antonio Bonifati 'Farmboy'
我太迷茫了... 我讨厌开源。 - Christine
显示剩余2条评论

9

你可以在MySQL查询浏览器或类似工具上执行以下命令:

SET old_passwords = 0;
UPDATE mysql.user SET Password = PASSWORD('testpass') WHERE User = 'testuser' limit 1;
SELECT LENGTH(Password) FROM mysql.user WHERE User = 'testuser';
FLUSH PRIVILEGES;

注意:您的用户名和密码

然后它就应该能够正常工作了。我也解决了我的问题。


1
这个解决方案只适用于你是数据库管理员或者拥有访问内部MySQL数据库权限的人。 - TehShrike

7

在OSX上,我使用MacPorts来解决连接到Siteground数据库时遇到的问题。Siteground似乎正在使用5.0.77mm0.1-log版本,但创建新用户账户并不能解决这个问题。以下是解决办法:

sudo port install php5-mysql -mysqlnd +mysql5

这将降级php使用的mysql驱动程序。

如何在需要的情况下升级回最新版本? - David
还有关于Windows方面的建议吗?安装旧版本的PHP(独立或与WAMP等一起)?我不认为在Windows上像在Mac上那样可以降级PHP的mySQL驱动程序。 - David
请注意降级可能会更改您系统中的 PHP 引用路径。在降级之前,调用 which php 命令,会显示 /usr/bin/php。降级后,它将更改为 /opt/local/bin/php,这可能是因为使用了 MacPorts,而之前它使用的是 Mac 系统默认的 PHP。但我的 PHPUnit 仍在 /usr/bin/phpunit 中。看起来我的 PHP 从 5.x(Mac OS X 10.6 上的默认版本)降级到了 2.3.0。但其中一个好处是,在此降级后我可以使用 mysql connect。希望降级不会带来其他问题。 - David
请忽略我的有关PHP版本的评论。我误读了PHP版本的Zend引擎版本。对于我来说,/usr/bin/php是5.3.4,/opt/local/bin/php是5.3.12。 - David

2
如果您没有管理员访问MySQL服务器配置(即,您正在使用托管服务),那么有两个选项可以使其工作:
1)请求将MySQL服务器上的old_passwords选项设置为false。
2)将PHP降级到5.2.2,直到选项1发生。
从我所能找到的信息来看,问题似乎出在MySQL帐户密码存储方式上,如果"old_passwords"设置为true,则会导致MySQL和较新版本的PHP(5.3+)之间存在兼容性问题。这会导致PHP尝试使用41个字符哈希值进行连接,但MySQL服务器仍然使用16个字符哈希值存储帐户密码。
此不兼容性是由MySQL 4.1中使用的哈希方法的更改引起的,该方法允许短和长哈希长度(请参见MySQL网站上此页面上的场景2:http://dev.mysql.com/doc/refman/5.5/en/password-hashing.html),以及在PHP 5.3中包含MySQL Native Driver(PHP文档的第7条记录了向后兼容性问题,请参见此页面:http://www.php.net/manual/en/migration53.incompatible.php)。

2

我遇到了相同的问题,但仅执行查询是无法解决的。为了解决这个问题,我按照以下步骤操作:

  1. 在my.cnf文件中设置old_passwords=0
  2. 重新启动mysql
  3. 以root用户身份登录mysql
  4. 执行FLUSH PRIVILEGES;

这个解决方案只适用于你是具有访问my.cnf文件的数据库管理员。 - TehShrike

0

如果:

  1. 您正在使用共享托管,并且没有根访问权限;
  2. 在连接到远程数据库时出现上述错误,即不是本地主机;
  3. 您正在使用Xampp;
  4. 代码在实际服务器上运行正常,但是在运行Xampp的开发机器上存在问题。

那么,我们强烈建议您安装xampp 1.7.0下载链接

注意:这不是解决上述问题的方法,而是一种修复方法,可以让您继续开发。


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