### 6.2.16 过期密码的服务器处理

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

MySQL 提供密码过期功能，使数据库管理员能够要求用户重置密码。密码可以手动过期，并根据自动过期策略（请参阅[第 6.2.15 节，“密码管理”](password-management.html)）。

这[`更改用户`](alter-user.html)语句启用帐户密码过期。例如：

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

对于使用过期密码帐户的每个连接，服务器要么断开客户端连接，要么将客户端限制为“沙盒模式”，在这种模式下，服务器只允许客户端执行重置过期密码所需的操作。服务器采取何种操作取决于客户端和服务器设置，稍后将讨论。

如果服务器断开客户端，它会返回一个[`ER_MUST_CHANGE_PASSWORD_LOGIN`](https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html#error_er_must_change_password_login)错误：

```
$> mysql -u myuser -p
Password: ******
ERROR 1862 (HY000): Your password has expired. To log in you must
change it using a client that supports expired passwords.
```

如果服务器将客户端限制为沙盒模式，则在客户端会话中允许执行以下操作：

-   客户可以使用重置帐户密码[`更改用户`](alter-user.html)要么[`设置密码`](set-password.html).完成后，服务器恢复会话的正常访问，以及使用该帐户的后续连接。

    笔记

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

-   在 MySQL 8.0.27 之前，客户端可以使用[`放`](set-variable.html)陈述。从 MySQL 8.0.27 开始，不再允许这样做。

    对于会话中不允许的任何操作，服务器返回一个[`ER_MUST_CHANGE_PASSWORD`](https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html#error_er_must_change_password)错误：


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

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

这就是交互调用通常会发生的情况[**mysql**](mysql.html)客户端，因为默认情况下，此类调用处于沙盒模式。要恢复正常功能，请选择一个新密码。

对于非交互式调用[**mysql**](mysql.html)客户端（例如，在批处理模式下），如果密码过期，服务器通常会断开客户端的连接。允许非交互[**mysql**](mysql.html)调用以保持连接以便可以更改密码（使用沙盒模式中允许的语句），添加[`--connect-expired-password`](mysql-command-options.html#option_mysql_connect-expired-password)选项[**mysql**](mysql.html)命令。

如前所述，服务器是否断开密码过期的客户端或将其限制为沙盒模式取决于客户端和服务器设置的组合。以下讨论描述了相关设置以及它们如何交互。

笔记

此讨论仅适用于密码过期的帐户。如果客户端使用未过期的密码进行连接，则服务器正常处理客户端。

在客户端，给定的客户端指示它是否可以处理过期密码的沙盒模式。对于使用 C 客户端库的客户端，有两种方法可以做到这一点：

-   通过`MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS`标记为[`mysql_options()`](https://dev.mysql.com/doc/c-api/8.0/en/mysql-options.html)连接前：

    ```
    bool arg = 1;
    mysql_options(mysql,
                  MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS,
                  &arg);
    ```

    这是内部使用的技术[**mysql**](mysql.html)客户端，它使`MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS`如果以交互方式调用或使用[`--connect-expired-password`](mysql-command-options.html#option_mysql_connect-expired-password)选项。

-   通过`CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS`标记为[`mysql_real_connect()`](https://dev.mysql.com/doc/c-api/8.0/en/mysql-real-connect.html)在连接时：

    ```
    MYSQL mysql;
    mysql_init(&mysql);
    if (!mysql_real_connect(&mysql,
                            host, user, password, db,
                            port, unix_socket,
                            CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS))
    {
      ... handle error ...
    }
    ```

    其他 MySQL 连接器有自己的约定来指示准备好处理沙盒模式。请参阅您感兴趣的连接器的文档。

    在服务器端，如果客户端表明它可以处理过期密码，服务器会将其置于沙盒模式。

    如果客户端没有表明它可以处理过期密码（或使用不能这样表明的旧版本的客户端库），则服务器操作取决于[`disconnect_on_expired_pa​​ssword`](server-system-variables.html#sysvar_disconnect_on_expired_password)系统变量：

-   如果[`disconnect_on_expired_pa​​ssword`](server-system-variables.html#sysvar_disconnect_on_expired_password)启用（默认），服务器断开客户端与[`ER_MUST_CHANGE_PASSWORD_LOGIN`](https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html#error_er_must_change_password_login)错误。

-   如果[`disconnect_on_expired_pa​​ssword`](server-system-variables.html#sysvar_disconnect_on_expired_password)被禁用，服务器将客户端置于沙盒模式。
