6.4.1.3 远离 4.1 之前的密码哈希和 mysql_old_password 插件迁移

MySQL 服务器使用plugin列中命名的身份验证插件来验证mysql.user系统 table 中列出的每个帐户的连接尝试。如果plugin列为空,则服务器按照以下方式对帐户进行身份验证:

  • 在 MySQL 5.7 之前,服务器会根据Password列中密码哈希的格式隐式使用mysql_native_passwordmysql_old_password插件。如果Password值为空或 4.1 密码哈希(41 个字符),则服务器使用mysql_native_password。如果密码值为 4.1 之前的密码哈希(16 个字符),则服务器使用mysql_old_password。 (有关这些哈希格式的更多信息,请参见第 6.1.2.4 节“ MySQL 中的密码哈希”。)

  • 从 MySQL 5.7 开始,服务器要求plugin列为非空,并禁用具有空plugin值的帐户。

在 MySQL 5.6 中不建议使用 4.1 之前的密码哈希和mysql_old_password插件,而在 MySQL 5.7 中则不再支持它们。它们提供的安全级别低于 4.1 密码哈希和mysql_native_password插件提供的安全级别。

鉴于 MySQL 5.7 中的要求,plugin列必须为非空,并取消了mysql_old_password支持,建议 DBA 如下升级帐户:

  • 升级隐式使用mysql_native_password的帐户以显式使用它

  • 升级使用mysql_old_password(隐式或显式)的帐户以显式使用mysql_native_password

本节中的说明描述了如何执行那些升级。结果是,没有帐户具有空的plugin值,并且没有帐户使用 4.1 之前的密码哈希或mysql_old_password插件。

作为这些说明的变体,DBA 可以为用户提供升级到sha256_password插件的选择,该插件使用 SHA-256 密码哈希进行身份验证。有关此插件的信息,请参见第 6.4.1.5 节“ SHA-256 可插拔身份验证”

下 table 列出了本讨论中考虑的mysql.user帐户的类型。

pluginPasswordAuthentication ResultUpgrade Action
EmptyEmpty隐式使用mysql_native_passwordAssign plugin
Empty4.1 hash隐式使用mysql_native_passwordAssign plugin
EmptyPre-4.1 hash隐式使用mysql_old_password分配插件,重新哈希密码
mysql_native_passwordEmpty明确使用mysql_native_passwordNone
mysql_native_password4.1 hash明确使用mysql_native_passwordNone
mysql_old_passwordEmpty明确使用mysql_old_passwordUpgrade plugin
mysql_old_passwordPre-4.1 hash明确使用mysql_old_password升级插件,重新哈希密码

对应于mysql_native_password插件行的帐户无需执行任何升级操作(因为无需更改插件或哈希格式)。对于与密码为空的行相对应的帐户,请考虑要求帐户所有者选择密码(或要求使用ALTER USER来使空帐户密码失效)。

将帐户从隐式升级为显式 mysql_native_password 使用

具有空插件和 4.1 密码哈希的帐户将隐式使用mysql_native_password。要将这些帐户升级为显式使用mysql_native_password,请执行以下语句:

UPDATE mysql.user SET plugin = 'mysql_native_password'
WHERE plugin = '' AND (Password = '' OR LENGTH(Password) = 41);
FLUSH PRIVILEGES;

在 MySQL 5.7 之前,您可以执行这些语句来主动更新帐户。从 MySQL 5.7 开始,您可以运行mysql_upgrade,它在其升级操作中执行相同的操作。

Notes:

  • 刚刚描述的升级操作可以随时执行,因为它使mysql_native_password插件仅对于已经隐式使用它的帐户才显式。

  • 此操作不需要更改密码,因此可以在不影响用户或不要求他们参与升级过程的情况下执行该操作。

将帐户从 mysql_old_password 升级到 mysql_native_password

使用mysql_old_password(隐式或显式)的帐户应升级为显式使用mysql_native_password。这需要更改插件,并将密码从 4.1 之前的哈希格式更改为 4.1 哈希格式。

对于此步骤中涉及的必须升级的帐户,以下条件之一为真:

  • 该帐户隐式使用mysql_old_password,因为plugin列为空,并且密码具有 4.1 之前的哈希格式(16 个字符)。

  • 该帐户明确使用mysql_old_password

要标识此类帐户,请使用以下查询:

SELECT User, Host, Password FROM mysql.user
WHERE (plugin = '' AND LENGTH(Password) = 16)
OR plugin = 'mysql_old_password';

以下讨论提供了两种更新该帐户组的方法。它们具有不同的特性,因此请阅读两者并确定哪种方法最适合给定的 MySQL 安装。

Method 1.

该方法的特点:

  • 它要求服务器和 Client 端使用secure_auth=0运行,直到所有用户都升级到mysql_native_password为止。 (否则,用户不能使用其旧格式的密码哈希连接到服务器,以升级到新格式的哈希.)

  • 它适用于 MySQL 5.5 和 5.6. 在 5.7 中,它不起作用,因为服务器要求帐户具有非空插件,否则将其禁用。因此,如果您已经升级到 5.7,请选择方法 2,如下所述。

您应该确保服务器以secure_auth=0运行。

对于所有明确使用mysql_old_password的帐户,请将其设置为空插件:

UPDATE mysql.user SET plugin = ''
WHERE plugin = 'mysql_old_password';
FLUSH PRIVILEGES;

要使受影响帐户的密码也过期,请改用以下语句:

UPDATE mysql.user SET plugin = '', password_expired = 'Y'
WHERE plugin = 'mysql_old_password';
FLUSH PRIVILEGES;

现在,受影响的用户可以重置其密码以使用 4.1 哈希。要求现在有一个空插件的每个用户连接到服务器并执行以下语句:

SET old_passwords = 0;
SET PASSWORD = PASSWORD('user-chosen-password');

Note

Client 端--secure-auth选项默认情况下处于启用状态,因此请提醒用户禁用它,否则他们将无法连接:

shell> mysql -u user_name -p --secure-auth=0

受影响的用户执行了这些语句后,可以将相应的帐户插件设置为mysql_native_password以使该插件显式。或者,您可以定期运行以下语句来查找和修复受影响的用户为其重置密码的任何帐户:

UPDATE mysql.user SET plugin = 'mysql_native_password'
WHERE plugin = '' AND (Password = '' OR LENGTH(Password) = 41);
FLUSH PRIVILEGES;

当不再有带有空插件的帐户时,此查询将返回空结果:

SELECT User, Host, Password FROM mysql.user
WHERE plugin = '' AND LENGTH(Password) = 16;

到那时,所有帐户都已从 4.1 之前的密码哈希迁移,并且不再需要使用secure_auth=0运行服务器。

Method 2.

该方法的特点:

  • 它会为每个受影响的帐户分配一个新密码,因此您必须向每个此类用户告知新密码,并要求用户选择一个新密码。与用户的密码通信不在 MySQL 的范围内,但应谨慎进行。

  • 它不需要使用secure_auth=0来运行服务器或 Client 端。

  • 它适用于 MySQL 5.5 或更高版本的任何版本(并且 5.7 具有更简单的变体)。

使用此方法,由于需要分别设置密码,因此需要分别更新每个帐户。 为每个帐户选择一个不同的密码.

假设'user1'@'localhost'是要升级的帐户之一。对其进行如下修改:

  • 在 MySQL 5.7 中,ALTER USER提供了修改帐户密码及其身份验证插件的功能,因此您无需直接修改mysql.user系统 table:
ALTER USER 'user1'@'localhost'
IDENTIFIED WITH mysql_native_password BY 'DBA-chosen-password';

要同时使帐户密码失效,请使用以下语句:

ALTER USER 'user1'@'localhost'
IDENTIFIED WITH mysql_native_password BY 'DBA-chosen-password'
PASSWORD EXPIRE;

然后告诉用户新密码,并要求用户使用该密码连接到服务器并执行以下语句以选择新密码:

ALTER USER USER() IDENTIFIED BY 'user-chosen-password';
  • 在 MySQL 5.7 之前,必须使用以下语句直接修改mysql.user系统 table:
SET old_passwords = 0;
UPDATE mysql.user SET plugin = 'mysql_native_password',
Password = PASSWORD('DBA-chosen-password')
WHERE (User, Host) = ('user1', 'localhost');
FLUSH PRIVILEGES;

要使帐户密码也过期,请改用以下语句:

SET old_passwords = 0;
UPDATE mysql.user SET plugin = 'mysql_native_password',
Password = PASSWORD('DBA-chosen-password'), password_expired = 'Y'
WHERE (User, Host) = ('user1', 'localhost');
FLUSH PRIVILEGES;

然后告诉用户新密码,并要求用户使用该密码连接到服务器并执行以下语句以选择新密码:

SET old_passwords = 0;
SET PASSWORD = PASSWORD('user-chosen-password');

对每个要升级的帐户重复上述步骤。