### 6.2.15 密码管理

[](<>)

MySQL 支持这些密码管理功能：

-   密码过期，要求定期更改密码。

-   密码重用限制，防止旧密码被再次选择。

-   密码验证，要求密码更改还指定要替换的当前密码。

-   双密码，使客户端能够使用主密码或辅助密码进行连接。

-   密码强度评估，要求使用强密码。

-   随机密码生成，作为要求明确的管理员指定的文字密码的替代方法。

-   密码失败跟踪，在连续多次错误密码登录失败后启用临时帐户锁定。

    以下部分描述了这些功能，但密码强度评估除外，它是使用`验证密码`组件，并在[第 6.4.3 节，“密码验证组件”](validate-password.html).

-   [内部与外部凭证存储](password-management.html#internal-versus-external-credentials)

-   [密码过期政策](password-management.html#password-expiration-policy)

-   [密码重用政策](password-management.html#password-reuse-policy)

-   [需要密码验证的策略](password-management.html#password-reverification-policy)

-   [双密码支持](password-management.html#dual-passwords)

-   [随机密码生成](password-management.html#random-password-generation)

-   [登录失败跟踪和临时帐户锁定](password-management.html#failed-login-tracking)

重要的

MySQL 使用表中的表实现密码管理功能`mysql`系统数据库。如果您从早期版本升级 MySQL，您的系统表可能不是最新的。在这种情况下，服务器会在启动过程中将类似于这些的消息写入错误日志（确切的数字可能会有所不同）：

```
[ERROR] Column count of mysql.user is wrong. Expected
49, found 47. The table is probably corrupted
[Warning] ACL table mysql.password_history missing.
Some operations may fail.
```

要更正此问题，请执行 MySQL 升级过程。看[第 2.11 节，“升级 MySQL”](upgrading.html).在这完成之前，*无法更改密码。*

#### 内部与外部凭证存储

一些身份验证插件将帐户凭据存储在MySQL内部的`mysql。使用者`系统表：

-   `mysql_本机_密码`

-   `缓存_sha2_密码`

-   `shau密码`

    本节中的大多数讨论适用于此类身份验证插件，因为这里描述的大多数密码管理功能都基于MySQL本身处理的内部凭证存储。其他身份验证插件将帐户凭据存储在MySQL外部。对于使用针对外部凭证系统执行身份验证的插件的帐户，密码管理也必须针对该系统进行外部处理。

    例外情况是，失败登录跟踪和临时帐户锁定选项适用于所有帐户，而不仅仅是使用内部凭据存储的帐户，因为MySQL能够评估任何帐户的登录尝试状态，无论其使用内部或外部凭据存储。

    有关单个身份验证插件的信息，请参阅[第6.4.1节，“认证插件”](authentication-plugins.html).

#### 密码过期策略

MySQL使数据库管理员能够手动使帐户密码过期，并建立自动密码过期策略。可以在全局范围内建立过期策略，并且可以将单个帐户设置为遵从全局策略，或者使用特定的每个帐户行为覆盖全局策略。

要手动终止帐户密码，请使用[`改变用户`](alter-user.html)声明：

```
ALTER USER 'jeffrey'@'localhost' PASSWORD EXPIRE;
```

此操作将在中的相应行中标记密码过期`mysql。使用者`系统表。

根据策略，密码过期是自动的，并且基于密码期限，对于给定帐户，密码期限从其最近一次密码更改的日期和时间开始评估。这个`mysql。使用者`系统表显示每个帐户上次更改密码的时间，如果密码的有效期大于其允许的生存期，服务器会在客户端连接时自动将其视为过期。这在没有明确的手动密码过期的情况下工作。

要全局建立自动密码过期策略，请使用[`默认密码生命周期`](server-system-variables.html#sysvar_default_password_lifetime)系统变量。其默认值为0，这将禁用自动密码过期。如果[`默认密码生命周期`](server-system-variables.html#sysvar_default_password_lifetime)是一个正整数*`N`*，它表示允许的密码生存期，因此密码必须每天更改*`N`*天。

例如：

-   要建立密码生命周期约为六个月的全局策略，请在服务器中使用以下行启动服务器`我的cnf`文件：

    ```
    [mysqld]
    default_password_lifetime=180
    ```

-   要建立全局策略以确保密码永不过期，请设置[`默认密码生命周期`](server-system-variables.html#sysvar_default_password_lifetime)到0:

    ```
    [mysqld]
    default_password_lifetime=0
    ```

-   [`默认密码生命周期`](server-system-variables.html#sysvar_default_password_lifetime)也可以在运行时进行设置和持久化：

    ```
    SET PERSIST default_password_lifetime = 180;
    SET PERSIST default_password_lifetime = 0;
    ```

     [`设定持续时间`](set-variable.html)为正在运行的MySQL实例设置一个值。它还保存了值，以便结转至后续服务器重启；看见[第13.7.6.1节，“设置变量赋值语法”](set-variable.html)。要更改正在运行的MySQL实例的值，而不将其带入后续重新启动，请使用`全球的`关键字而不是`坚持`.

    全局密码过期策略适用于所有尚未设置为覆盖它的帐户。要为个人帐户建立策略，请使用`密码过期`选择[`创建用户`](create-user.html)和[`改变用户`](alter-user.html)声明。看见[第13.7.1.3节“创建用户声明”](create-user.html)和[第13.7.1.1节“更改用户声明”](alter-user.html).

    特定于账户的报表示例：

-   要求每90天更改一次密码：

    ```
    CREATE USER 'jeffrey'@'localhost' PASSWORD EXPIRE INTERVAL 90 DAY;
    ALTER USER 'jeffrey'@'localhost' PASSWORD EXPIRE INTERVAL 90 DAY;
    ```

    此过期选项将覆盖对账单指定的所有帐户的全局策略。

-   禁用密码过期：

    ```
    CREATE USER 'jeffrey'@'localhost' PASSWORD EXPIRE NEVER;
    ALTER USER 'jeffrey'@'localhost' PASSWORD EXPIRE NEVER;
    ```

    此过期选项将覆盖对账单指定的所有帐户的全局策略。

-   对账单中指定的所有账户遵守全球到期政策：

    ```
    CREATE USER 'jeffrey'@'localhost' PASSWORD EXPIRE DEFAULT;
    ALTER USER 'jeffrey'@'localhost' PASSWORD EXPIRE DEFAULT;
    ```

    当客户端成功连接时，服务器将确定帐户密码是否已过期：

-   服务器会检查密码是否已手动过期。

-   否则，服务器将根据自动密码过期策略检查密码期限是否大于其允许的生存期。如果是，服务器将认为密码已过期。

    如果密码过期（手动或自动），服务器会断开客户机的连接或限制其允许的操作（请参阅）[第6.2.16节，“过期密码的服务器处理”](expired-password-handling.html))。在用户建立新帐户密码之前，受限客户端执行的操作会导致错误：

[](<>)[](<>)[](<>)

```
mysql> SELECT 1;
ERROR 1820 (HY000): You must reset your password using ALTER USER
statement before executing this statement.

mysql> ALTER USER USER() IDENTIFIED BY 'password';
Query OK, 0 rows affected (0.01 sec)

mysql> SELECT 1;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.00 sec)
```

客户端重置密码后，服务器将恢复会话以及使用该帐户的后续连接的正常访问。管理用户也可以重置帐户密码，但该帐户的任何现有受限会话仍然受限。在成功执行语句之前，使用该帐户的客户端必须断开连接并重新连接。

笔记

虽然可以通过将过期密码设置为其当前值来“重置”过期密码，但作为一项良好的策略，最好选择不同的密码。DBA可以通过建立适当的密码重用策略来强制不重用。看见[密码重用策略](password-management.html#password-reuse-policy).

#### 密码重用策略

MySQL允许限制重复使用以前的密码。可以根据密码更改的次数、经过的时间或两者来建立重用限制。可以在全局范围内建立重用策略，并且可以将单个帐户设置为遵从全局策略，或者使用特定的每个帐户行为覆盖全局策略。

帐户的密码历史记录由过去分配的密码组成。MySQL可以限制从以下历史记录中选择新密码：

-   如果根据密码更改次数限制帐户，则无法从指定数量的最新密码中选择新密码。例如，如果密码更改的最小次数设置为3，则新密码不能与最近的3个密码中的任何一个相同。

-   如果根据时间限制帐户，则无法从历史记录中比指定天数新的密码中选择新密码。例如，如果密码重复使用间隔设置为60，则新密码不得出现在过去60天内之前选择的密码中。

笔记

空密码不计入密码历史记录，可随时重新使用。

要在全局范围内建立密码重用策略，请使用[`密码历史`](server-system-variables.html#sysvar_password_history)和[`密码_重用_间隔`](server-system-variables.html#sysvar_password_reuse_interval)系统变量。

例如：

-   要禁止重复使用最后6个密码中的任何一个或超过365天的密码，请在服务器中输入以下行`我的cnf`文件：

    ```
    [mysqld]
    password_history=6
    password_reuse_interval=365
    ```

-   要在运行时设置并保存变量，请使用以下语句：

    ```
    SET PERSIST password_history = 6;
    SET PERSIST password_reuse_interval = 365;
    ```

     [`设定持续时间`](set-variable.html)为正在运行的MySQL实例设置一个值。它还保存了值，以便结转至后续服务器重启；看见[第13.7.6.1节，“设置变量赋值语法”](set-variable.html)。要更改正在运行的MySQL实例的值，而不将其带入后续重新启动，请使用`全球的`关键字而不是`坚持`.

    全局密码重用策略适用于所有尚未设置为覆盖它的帐户。要为个人帐户建立策略，请使用`密码历史记录`和`密码重复使用间隔`政府的选择[`创建用户`](create-user.html)和[`改变用户`](alter-user.html)声明。看见[第13.7.1.3节“创建用户声明”](create-user.html)和[第13.7.1.1节“更改用户声明”](alter-user.html).

    特定于账户的报表示例：

-   在允许重新使用之前，至少需要更改5次密码：

    ```
    CREATE USER 'jeffrey'@'localhost' PASSWORD HISTORY 5;
    ALTER USER 'jeffrey'@'localhost' PASSWORD HISTORY 5;
    ```

    此历史长度选项将覆盖由该语句命名的所有帐户的全局策略。

-   在允许重复使用之前，至少需要365天：

    ```
    CREATE USER 'jeffrey'@'localhost' PASSWORD REUSE INTERVAL 365 DAY;
    ALTER USER 'jeffrey'@'localhost' PASSWORD REUSE INTERVAL 365 DAY;
    ```

    此“已用时间”选项将覆盖由该语句命名的所有帐户的全局策略。

-   要结合这两种类型的重用限制，请使用`密码历史记录`和`密码重复使用间隔`一起：

    ```
    CREATE USER 'jeffrey'@'localhost'
      PASSWORD HISTORY 5
      PASSWORD REUSE INTERVAL 365 DAY;
    ALTER USER 'jeffrey'@'localhost'
      PASSWORD HISTORY 5
      PASSWORD REUSE INTERVAL 365 DAY;
    ```

    这些选项覆盖了对由该语句命名的所有帐户的全局策略重用限制。

-   对于这两种类型的重用限制，请遵循全局策略：

    ```
    CREATE USER 'jeffrey'@'localhost'
      PASSWORD HISTORY DEFAULT
      PASSWORD REUSE INTERVAL DEFAULT;
    ALTER USER 'jeffrey'@'localhost'
      PASSWORD HISTORY DEFAULT
      PASSWORD REUSE INTERVAL DEFAULT;
    ```

#### 需要密码验证的策略

从MySQL 8.0.13开始，可以要求通过指定要替换的当前密码来验证更改帐户密码的尝试。这使DBA能够防止用户在不证明他们知道当前密码的情况下更改密码。否则，这种更改可能会发生，例如，如果一个用户暂时离开终端会话而没有注销，恶意用户使用该会话更改原始用户的MySQL密码。这可能会产生不幸的后果：

-   在管理员重置帐户密码之前，原始用户将无法访问MySQL。

-   在密码重置发生之前，恶意用户可以使用良性用户更改的凭据访问MySQL。

    可以在全局范围内建立密码验证策略，并且可以将单个帐户设置为遵从全局策略，或者使用特定的每个帐户行为覆盖全局策略。

    对于每个帐户，其`mysql。使用者`行指示是否存在特定于帐户的设置，需要验证密码更改尝试的当前密码。该设置由`密码要求`选择[`创建用户`](create-user.html)和[`改变用户`](alter-user.html)声明：

-   如果帐户设置为`密码需要当前密码`，密码更改必须指定当前密码。

-   如果帐户设置为`密码要求当前可选`，密码更改可能但不需要指定当前密码。

-   如果帐户设置为`密码需要当前默认值`这个[`密码\u需要\u当前密码`](server-system-variables.html#sysvar_password_require_current)系统变量确定帐户所需的验证策略：

    -   如果[`密码\u需要\u当前密码`](server-system-variables.html#sysvar_password_require_current)如果启用，密码更改必须指定当前密码。

    -   如果[`密码\u需要\u当前密码`](server-system-variables.html#sysvar_password_require_current)已禁用，密码更改可能但无需指定当前密码。

    换句话说，如果帐户设置不正确`密码需要当前默认值`，帐户设置优先于[`密码\u需要\u当前密码`](server-system-variables.html#sysvar_password_require_current)系统变量。否则，该账户将根据[`密码\u需要\u当前密码`](server-system-variables.html#sysvar_password_require_current)背景

    默认情况下，密码验证是可选的：[`密码\u需要\u当前密码`](server-system-variables.html#sysvar_password_require_current)已禁用，并且创建的帐户没有`密码要求`选项默认为`密码需要当前默认值`.

    下表显示了每个帐户设置如何与[`密码\u需要\u当前密码`](server-system-variables.html#sysvar_password_require_current)确定帐户密码验证所需策略的系统变量值。

[](<>)

**表6.10密码验证策略**

| 按帐户设置 | 暗语\_要求\_当前系统变量 | 密码更改需要当前密码吗？ |
| ----- | -------------- | ------------ |
| `密码需要当前密码` | `关` | 对 |
| `密码需要当前密码` | `在…上` | 对 |
| `密码要求当前可选` | `关` | 不 |
| `密码要求当前可选` | `在…上` | 不 |
| `密码需要当前默认值` | `关` | 不 |
| `密码需要当前默认值` | `在…上` | 对 |

笔记

特权用户可以更改任何帐户密码，而无需指定当前密码，而无需考虑所需的验证策略。特权用户是指拥有全局权限的用户[`创建用户`](privileges-provided.html#priv_create-user)特权还是[`使现代化`](privileges-provided.html#priv_update)特权`mysql`系统数据库。

要全局建立密码验证策略，请使用[`密码\u需要\u当前密码`](server-system-variables.html#sysvar_password_require_current)系统变量。其默认值为`关`，因此不需要更改帐户密码来指定当前密码。

例如：

-   要建立密码更改必须指定当前密码的全局策略，请在服务器中使用以下行启动服务器`我的cnf`文件：

    ```
    [mysqld]
    password_require_current=ON
    ```

-   坚持[`密码\u需要\u当前密码`](server-system-variables.html#sysvar_password_require_current)在运行时，使用以下语句之一：

    ```
    SET PERSIST password_require_current = ON;
    SET PERSIST password_require_current = OFF;
    ```

     [`设定持续时间`](set-variable.html)为正在运行的MySQL实例设置一个值。它还保存了值，以便结转至后续服务器重启；看见[第13.7.6.1节，“设置变量赋值语法”](set-variable.html)。要更改正在运行的MySQL实例的值，而不将其带入后续重新启动，请使用`全球的`关键字而不是`坚持`.

    “需要全局密码验证”策略适用于所有尚未设置为覆盖该策略的帐户。要为个人帐户建立策略，请使用`密码要求`政府的选择[`创建用户`](create-user.html)和[`改变用户`](alter-user.html)声明。看见[第13.7.1.3节“创建用户声明”](create-user.html)和[第13.7.1.1节“更改用户声明”](alter-user.html).

    特定于账户的报表示例：

-   要求密码更改指定当前密码：

    ```
    CREATE USER 'jeffrey'@'localhost' PASSWORD REQUIRE CURRENT;
    ALTER USER 'jeffrey'@'localhost' PASSWORD REQUIRE CURRENT;
    ```

    此验证选项将覆盖对账单指定的所有帐户的全局策略。

-   不要求密码更改指定当前密码（可以但不需要提供当前密码）：

    ```
    CREATE USER 'jeffrey'@'localhost' PASSWORD REQUIRE CURRENT OPTIONAL;
    ALTER USER 'jeffrey'@'localhost' PASSWORD REQUIRE CURRENT OPTIONAL;
    ```

    此验证选项将覆盖对账单指定的所有帐户的全局策略。

-   对于该对账单中指定的所有帐户，请遵守全球密码验证所需的策略：

    ```
    CREATE USER 'jeffrey'@'localhost' PASSWORD REQUIRE CURRENT DEFAULT;
    ALTER USER 'jeffrey'@'localhost' PASSWORD REQUIRE CURRENT DEFAULT;
    ```

    当用户使用[`改变用户`](alter-user.html)或[`设置密码`](set-password.html)陈述这些例子使用[`改变用户`](alter-user.html)，哪一个更受欢迎[`设置密码`](set-password.html)，但这里描述的原则对这两种说法都是一样的。

    在密码更改语句中`代替`子句指定要替换的当前密码。例如：

-   更改当前用户的密码：

    ```
    ALTER USER USER() IDENTIFIED BY 'auth_string' REPLACE 'current_auth_string';
    ```

-   更改命名用户的密码：

    ```
    ALTER USER 'jeffrey'@'localhost'
      IDENTIFIED BY 'auth_string'
      REPLACE 'current_auth_string';
    ```

-   更改命名用户的身份验证插件和密码：

    ```
    ALTER USER 'jeffrey'@'localhost'
      IDENTIFIED WITH caching_sha2_password BY 'auth_string'
      REPLACE 'current_auth_string';
    ```

    这个`代替`第条的作用如下：

-   `代替`如果需要更改帐户密码以指定当前密码，则必须提供，以验证试图进行更改的用户是否确实知道当前密码。

-   `代替`如果帐户的密码更改可能但不需要指定当前密码，则为可选。

-   如果`代替`则必须指定正确的当前密码，否则将发生错误。即使`代替`是可选的。

-   `代替`只能在更改当前用户的帐户密码时指定。（这意味着在刚才显示的示例中，明确指定帐户的语句`杰弗里`除非当前用户`杰弗里`）即使特权用户尝试对另一个用户进行更改，这也是正确的；但是，这样的用户可以更改任何密码，而无需指定`代替`.

-   `代替`从二进制日志中省略，以避免向其写入明文密码。

#### 双密码支持

[](<>)[](<>)[](<>)[](<>)

从MySQL 8.0.14开始，用户帐户被允许有双重密码，指定为主密码和辅助密码。双密码功能使您能够在以下情况下无缝执行凭证更改：

-   一个系统有大量MySQL服务器，可能涉及复制。

-   多个应用程序连接到不同的MySQL服务器。

-   必须定期更改应用程序用于连接到服务器的一个或多个帐户的凭据。

    考虑在只有一个口令允许帐户时，必须在前面类型的方案中执行凭据更改。在这种情况下，必须密切合作，确定何时更改帐户密码并在所有服务器上传播，以及何时更新使用该帐户的所有应用程序以使用新密码。此过程可能涉及停机，在此期间服务器或应用程序不可用。

    使用双密码，可以更轻松地分阶段更改凭证，无需密切合作，也无需停机：

1.  对于每个受影响的帐户，在服务器上建立一个新的主密码，将当前密码保留为辅助密码。这使服务器能够识别每个帐户的主密码或辅助密码，而应用程序可以继续使用与以前相同的密码（现在是辅助密码）连接到服务器。

2.  密码更改传播到所有服务器后，请修改使用任何受影响帐户的应用程序，以使用帐户主密码进行连接。

3.  在所有应用程序都从次要密码迁移到主要密码后，次要密码不再需要，可以丢弃。此更改传播到所有服务器后，只能使用每个帐户的主密码进行连接。凭证更改现在已完成。

    MySQL通过保存和丢弃辅助密码的语法实现了双密码功能：

-   这个`保留当前密码`合同条款[`改变用户`](alter-user.html)和[`设置密码`](set-password.html)在分配新的主密码时，语句会将帐户当前密码保存为其辅助密码。

-   这个`丢弃旧密码`条款[`改变用户`](alter-user.html)放弃帐户辅助密码，只保留主密码。

    假设在前面描述的凭证更改场景中，一个名为`“appuser1@”主机1。实例com'`由应用程序用于连接到服务器，并更改帐户密码`'*`密码a`*'`到`'*`密码`*'`.

    要执行此凭据更改，请使用`改变用户`详情如下：

1.  在每个不是副本的服务器上，建立`'*`密码`*'`作为新的`appuser1`主密码，保留当前密码作为辅助密码：

    ```
    ALTER USER 'appuser1'@'host1.example.com'
      IDENTIFIED BY 'password_b'
      RETAIN CURRENT PASSWORD;
    ```

2.  等待密码更改在整个系统中复制到所有副本。

3.  修改使用`appuser1`帐户，以便使用密码连接到服务器`'*`密码`*'`而不是`'*`密码a`*'`.

4.  此时，不再需要第二个密码。在每个不是副本的服务器上，放弃辅助密码：

    ```
    ALTER USER 'appuser1'@'host1.example.com'
      DISCARD OLD PASSWORD;
    ```

5.  放弃密码更改复制到所有副本后，凭证更改完成。

    这个`保留当前密码`和`丢弃旧密码`条款具有以下效力：

-   `保留当前密码`保留帐户当前密码作为其辅助密码，替换任何现有辅助密码。新密码将成为主密码，但客户端可以使用该帐户使用主密码或辅助密码连接到服务器。（例外情况：如果[`改变用户`](alter-user.html)或[`设置密码`](set-password.html)语句为空时，辅助密码也将变为空，即使`保留当前密码`（已给出。）

-   如果你指定`保留当前密码`对于主密码为空的帐户，该语句将失败。

-   如果一个帐户有一个辅助密码，而您在没有指定密码的情况下更改了它的主密码`保留当前密码`，辅助密码保持不变。

-   对于[`改变用户`](alter-user.html)，如果更改分配给该帐户的身份验证插件，则会丢弃辅助密码。如果更改身份验证插件并指定`保留当前密码`声明失败了。

-   对于[`改变用户`](alter-user.html), `丢弃旧密码`丢弃辅助密码（如果存在）。该帐户只保留其主密码，客户端只能使用该帐户以主密码连接到服务器。

    修改辅助密码的语句需要以下权限：

-   这个[`应用程序\密码\管理员`](privileges-provided.html#priv_application-password-admin)使用`保留当前密码`或`丢弃旧密码`条款[`改变用户`](alter-user.html)和[`设置密码`](set-password.html)适用于您自己账户的对账单。由于大多数用户只需要一个密码，因此需要该权限来操作自己的辅助密码。

-   如果允许一个帐户操作所有帐户的辅助密码，则应授予该帐户[`创建用户`](privileges-provided.html#priv_create-user)特权而不是[`应用程序\密码\管理员`](privileges-provided.html#priv_application-password-admin).

#### 随机密码生成

从MySQL 8.0.18开始[`创建用户`](create-user.html), [`改变用户`](alter-user.html)和[`设置密码`](set-password.html)语句具有为用户帐户生成随机密码的能力，这是要求明确的管理员指定的文字密码的替代方法。有关语法的详细信息，请参见每条语句的描述。本节介绍生成的随机密码的常见特征。

默认情况下，生成的随机密码长度为20个字符。此长度由[`生成的\u随机\u密码\u长度`](server-system-variables.html#sysvar_generated_random_password_length)系统变量，其范围为5到255。

对于语句生成随机密码的每个帐户，该语句将密码存储在`mysql。使用者`系统表，对帐户身份验证插件进行了适当的哈希处理。该语句还返回结果集中一行的明文密码，以使执行该语句的用户或应用程序可以使用该密码。结果集列被命名为`使用者`, `主办`和`生成的密码`，指示标识中受影响行的用户名和主机名值`mysql。使用者`系统表，以及明文生成的密码。

```
mysql> CREATE USER
       'u1'@'localhost' IDENTIFIED BY RANDOM PASSWORD,
       'u2'@'%.example.com' IDENTIFIED BY RANDOM PASSWORD,
       'u3'@'%.org' IDENTIFIED BY RANDOM PASSWORD;
+------+---------------+----------------------+
| user | host          | generated password   |
+------+---------------+----------------------+
| u1   | localhost     | BA;42VpXqQ@i+y{&TDFF |
| u2   | %.example.com | YX5>XRAJRP@>sn9azmD4 |
| u3   | %.org         | ;GfD44l,)C}PI/6)4TwZ |
+------+---------------+----------------------+
mysql> ALTER USER
       'u1'@'localhost' IDENTIFIED BY RANDOM PASSWORD,
       'u2'@'%.example.com' IDENTIFIED BY RANDOM PASSWORD;
+------+---------------+----------------------+
| user | host          | generated password   |
+------+---------------+----------------------+
| u1   | localhost     | yhXBrBp.;Y6abB)e_UWr |
| u2   | %.example.com | >M-vmjp9DTY6}hkp,RcC |
+------+---------------+----------------------+
mysql> SET PASSWORD FOR 'u3'@'%.org' TO RANDOM;
+------+-------+----------------------+
| user | host  | generated password   |
+------+-------+----------------------+
| u3   | %.org | o(._oNn)d;FC<vJIDg9M |
+------+-------+----------------------+
```

A.[`创建用户`](create-user.html), [`改变用户`](alter-user.html)或[`设置密码`](set-password.html)为帐户生成随机密码的语句作为密码写入二进制日志[`创建用户`](create-user.html)或[`改变用户`](alter-user.html)带有`认同*`auth\_插件`*就像*`验证字符串`*'`，子句，其中*`auth_插件`*是帐户身份验证插件和`'*`验证字符串`*'`是帐户哈希密码值。

如果`验证密码`组件安装后，它实现的策略对生成的密码没有影响。（密码验证的目的是帮助人类创建更好的密码。）

#### 登录跟踪和临时帐户锁定失败

从MySQL 8.0.19开始，管理员可以配置用户帐户，以便连续多次登录失败会导致临时帐户锁定。

在此上下文中，“登录失败”指的是客户端在连接尝试期间未能提供正确的密码。它不包括由于未知用户或网络问题等原因导致的连接失败。对于具有双重密码的帐户（请参阅[双密码支持](password-management.html#dual-passwords))，任一帐户密码均视为正确。

所需的登录失败次数和锁定时间可使用`登录尝试失败`和`密码锁定时间`政府的选择[`创建用户`](create-user.html)和[`改变用户`](alter-user.html)声明。例如：

```
CREATE USER 'u1'@'localhost' IDENTIFIED BY 'password'
  FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 3;

ALTER USER 'u2'@'localhost'
  FAILED_LOGIN_ATTEMPTS 4 PASSWORD_LOCK_TIME UNBOUNDED;
```

当连续出现太多登录失败时，客户端会收到如下错误：

```
ERROR 3957 (HY000): Access denied for user user.
Account is blocked for D day(s) (R day(s) remaining)
due to N consecutive failed logins.
```

使用以下选项：

-   `登录尝试失败*`N`*`

    此选项指示是否跟踪指定错误密码的帐户登录尝试。号码*`N`*指定导致临时帐户锁定的连续错误密码数。

-   `密码锁定时间{*`N`*|无界}`

    此选项指示连续多次登录尝试提供错误密码后锁定帐户的时间。该值是一个数字*`N`*指定帐户保持锁定的天数，或`无限的`指定当帐户进入临时锁定状态时，该状态的持续时间是无限的，直到帐户解锁后才会结束。解锁发生的条件将在后面描述。

    允许值*`N`*每个选项的值都在0到32767之间。值为0将禁用该选项。

    失败的登录跟踪和临时帐户锁定具有以下特征：

-   对于失败的登录跟踪和帐户的临时锁定，其`登录尝试失败`和`密码锁定时间`选项都必须为非零。

-   对于[`创建用户`](create-user.html)如果`登录尝试失败`或`密码锁定时间`如果未指定，则对于由语句命名的所有帐户，其隐式默认值为0。这意味着将禁用失败的登录跟踪和临时帐户锁定。（这些隐式默认值也适用于引入失败登录跟踪之前创建的帐户。）

-   对于[`改变用户`](alter-user.html)如果`登录尝试失败`或`密码锁定时间`如果未指定，则对于该对账单指定的所有帐户，其值保持不变。

-   要进行临时帐户锁定，密码失败必须是连续的。在到达服务器之前发生的任何成功登录`登录尝试失败`失败登录的值会导致重置失败计数。例如，如果`登录尝试失败`is 4，并且连续发生三次密码失败，需要再次失败才能开始锁定。但如果下一次登录成功，则会重置帐户的失败登录计数，以便再次需要连续四次失败才能锁定。

-   一旦临时锁定开始，即使使用正确的密码，也无法成功登录，除非锁定持续时间已过，或者通过以下讨论中列出的帐户重置方法之一解锁帐户。

    当服务器读取授权表时，它会初始化每个帐户的状态信息，这些信息涉及是否启用了失败的登录跟踪、帐户当前是否被临时锁定以及锁定何时开始（如果是），以及如果帐户未被锁定，在发生临时锁定之前的失败次数。

    可以重置帐户的状态信息，这意味着重置失败的登录计数，如果当前暂时锁定，则帐户将解锁。账户重置可以是所有账户或每个账户的全局重置：

-   在以下任何情况下，都会对所有帐户进行全局重置：

    -   服务器重启。

    -   执行[`同花顺特权`](flush.html#flush-privileges)（使用启动服务器）[`--跳过拨款表`](server-options.html#option_mysqld_skip-grant-tables)导致无法读取授权表，这将禁用失败的登录跟踪。在这种情况下，第一次执行[`同花顺特权`](flush.html#flush-privileges)除了重置所有帐户外，还会导致服务器读取授权表并启用失败的登录跟踪。）

-   在以下任何情况下，每个帐户都会重置：

    -   成功登录帐户。

    -   锁的持续时间过去了。在这种情况下，失败的登录计数会在下次登录尝试时重置。

    -   执行[`改变用户`](alter-user.html)设置`登录尝试失败`或`密码锁定时间`（或两者兼有）任何价值（包括当前期权价值），或执行[`改变用户。。。解锁`](alter-user.html)对账单。

        另外[`改变用户`](alter-user.html)帐户的语句对其当前失败的登录计数或锁定状态没有影响。

    失败的登录跟踪绑定到用于检查凭据的登录帐户。如果正在使用用户代理，则会对代理用户而不是被代理的用户进行跟踪。也就是说，跟踪与[`用户（）`](information-functions.html#function_user)，而非[`当前用户（）`](information-functions.html#function_current-user)。有关代理和代理用户之间的区别的信息，请参阅[第6.2.19节“代理用户”](proxy-users.html).
