• 首页
  • css3教程
  • html5教程
  • jQuery手册
  • vue手册
  • php手册
  • MySQL手册
  • apache手册
  • redis手册
  • 帐户密码管理

    分配帐户密码

    连接到MySQL服务器的客户端所需的凭据可以包括密码。本节介绍如何为MySQL帐户分配密码。

    MySQL将凭据存储在系统数据库的user表中mysql。分配或修改密码的操作仅授予具有以下CREATE USER特权的用户,或者具有mysql数据库INSERT特权(创建新帐户的UPDATE特权,修改现有帐户的特权)的用户。如果read_only启用了系统变量,则使用帐户修改语句,例如CREATE USER或,ALTER USER另外需要CONNECTION_ADMINSUPER特权。

    此处的讨论仅汇总了最常见的密码分配语句的语法。有关其他可能性的完整详细信息,请参见“创建账户”,“ ALTER USER语句”和“ SET PASSWORD语句”。

    MySQL使用插件执行客户端身份验证;在密码分配语句中,与帐户关联的身份验证插件对指定的明文密码执行所需的任何哈希处理。这样,MySQL可以先对密码进行混淆处理,然后再将其存储在mysql.user系统表中。对于此处描述的语句,MySQL自动哈希指定的密码。还有用于的语法CREATE USERALTER USER该语法允许按字面值指定散列值。有关详细信息,请参见这些语句的描述。

    要在创建新帐户时分配密码,请使用CREATE USER并包含一个IDENTIFIED BY子句:

    CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'password';
    

    CREATE USER还支持用于指定帐户身份验证插件的语法。请参见“ CREATE USER语句”。

    要为现有帐户分配或更改密码,请将该ALTER USER语句与以下IDENTIFIED BY子句一起使用:

    ALTER USER 'jeffrey'@'localhost' IDENTIFIED BY 'password';
    

    如果您不是以匿名用户身份连接的,则可以更改自己的密码,而无需直接命名自己的帐户:

    ALTER USER USER() IDENTIFIED BY 'password';
    

    要从命令行更改帐户密码,请使用mysqladmin命令:

    mysqladmin -u user_name -h host_name password "password"
    

    针对该命令设置密码的帐户是在一个与行mysql.user系统表匹配user_nameUser列和客户端主机从中连接Host列。

    警告

    使用mysqladmin设置密码应该被认为是不安全的。在某些系统上,您的密码对系统状态程序(例如ps)可见,其他用户可能会调用该密码来显示命令行。MySQL客户端通常在初始化序列期间用零覆盖命令行密码参数。但是,仍然存在一个短暂的时间间隔,在此间隔内该值是可见的。同样,在某些系统上,这种覆盖策略无效,并且ps仍然可以看到密码。(SystemV Unix系统以及其他系统可能会遇到此问题。)

    如果您使用的是MySQL复制,请注意,当前,复制从站用作CHANGE MASTER TO语句一部分的密码长度实际上限制为32个字符;如果密码较长,则多余的字符将被截断。这并不是由于MySQL Server通常施加的任何限制,而是MySQL复制特有的问题。(有关更多信息,请参见Bug#43439。)


    密码管理

    MySQL支持以下密码管理功能:

    • 密码到期,要求定期更改密码。
    • 密码重用限制,以防止再次选择旧密码。
    • 密码验证,要求更改密码还指定要替换的当前密码。
    • 双密码,使客户端可以使用主密码或辅助密码进行连接。
    • 密码强度评估,要求使用强密码。
    • 随机密码生成,作为要求管理员指定明确的文字密码的替代方法。
    • 密码故障跟踪,以在连续多次错误密码登录失败后启用临时帐户锁定。

    以下各节介绍了这些功能,但密码强度评估除外,密码强度评估是使用该validate_password组件实现的,并在“密码验证组件”中进行了介绍。

    • 内部与外部凭证存储
    • 密码过期政策
    • 密码重用政策
    • 密码验证要求的政策
    • 双密码支持
    • 随机密码生成
    • 登录失败跟踪和临时帐户锁定
    重要

    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升级过程。请参见“升级MySQL”。在此之前,无法更改密码。

    内部与外部凭证存储

    一些身份验证插件将帐户凭据存储在MySQL内部的mysql.user系统表中:

    • mysql_native_password
    • caching_sha2_password
    • sha256_password

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

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

    有关单个身份验证插件的信息,请参见“编写身份验证插件”。

    密码过期政策

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

    要手动使帐户密码失效,请使用以下ALTER USER语句:

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

    此操作在mysql.user系统表的相应行中标记密码已过期。

    根据策略,密码有效期是自动的,并且基于密码有效期,对于给定帐户,将从最近一次密码更改的日期和时间开始评估。该mysql.user系统表显示为每个帐户时,其上次更改口令,服务器自动将作为客户端连接的过期时间,如果它的年龄比它允许生存更大的口令。此方法无需明确的手动密码有效期。

    要全局建立自动密码过期策略,请使用default_password_lifetime系统变量。其默认值为0,这将禁用自动密码过期。如果的值default_password_lifetime是正整数N,则表示允许的密码有效期,因此必须每天更改密码N

    例子:

    • 要建立密码有效期大约为六个月的全局策略,请在服务器my.cnf文件中使用以下几行来启动服务器:

      [mysqld]
      default_password_lifetime=180
      
    • 要建立全局策略以使密码永不过期,请将其设置default_password_lifetime为0:

      [mysqld]
      default_password_lifetime=0
      
    • default_password_lifetime也可以在运行时设置和持久化:

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

      SET PERSIST设置正在运行的MySQL实例的值。它还保存了用于后续服务器重新启动的值。请参见“变量分配的SET语法”。要更改正在运行的MySQL实例的值而不保存该值以供以后重新启动,请使用GLOBAL关键字而不是PERSIST

    全局密码过期策略适用于尚未设置为覆盖该策略的所有帐户。要为单个帐户建立政策,请使用和语句的PASSWORD EXPIRE选项。请参见“ CREATE USER语句”和“ ALTER USER语句”。CREATE USERALTER USER

    特定于帐户的语句示例:

    • 要求每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;
      

    客户端成功连接后,服务器将确定帐户密码是否已过期:

    • 服务器检查密码是否已手动过期。
    • 否则,服务器会根据自动密码过期策略检查密码使用期限是否大于其允许的使用期限。如果是这样,则服务器认为密码已过期。

    如果密码已过期(无论是手动还是自动),服务器将断开客户端连接或限制其允许的操作(请参见“服务器处理过期的密码”)。受限制的客户端执行的操作会导致错误,直到用户建立新的帐户密码为止:

    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可以通过建立适当的密码重用策略来强制不重用。请参阅密码重用策略。

    密码重用政策

    MySQL允许对重用以前的密码进行限制。可以根据密码更改的次数,经过的时间或同时基于两者来建立重用限制。可以在全球范围内建立重用策略,并且可以将各个帐户设置为服从全局策略,或者使用特定的按帐户行为替换全局策略。

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

    • 如果根据密码更改次数限制了帐户,则无法从指定数量的最新密码中选择新密码。例如,如果密码更改的最小次数设置为3,则新密码不能与最新的3个密码相同。
    • 如果根据时间限制了帐户,则无法从历史记录中指定天数以上的密码中选择新密码。例如,如果密码重用间隔设置为60,则新密码一定不能属于过去60天内先前选择的密码。
    注意

    空密码不计入密码历史记录,并且随时可以重复使用。

    要全局建立密码重用策略,请使用password_historypassword_reuse_interval系统变量。

    例子:

    • 要禁止重复使用最近6个密码或365天以内的密码,请在服务器my.cnf文件中添加以下行:

      [mysqld]
      password_history=6
      password_reuse_interval=365
      
    • 要在运行时设置和保留变量,请使用如下语句:

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

      SET PERSIST设置正在运行的MySQL实例的值。它还保存了用于后续服务器重新启动的值。请参见“变量分配的SET语法”。要更改正在运行的MySQL实例的值而不保存该值以供以后重新启动,请使用GLOBAL关键字而不是PERSIST

    全局密码重用策略适用于尚未设置为覆盖它的所有帐户。要为单个帐户建立政策,请使用和语句的PASSWORD HISTORYPASSWORD REUSE INTERVAL选项。请参见“ CREATE USER语句”和“ ALTER USER语句”。CREATE USERALTER USER

    特定于帐户的语句示例:

    • 在允许重复使用之前,至少需要更改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;
      

      这个经过时间的选项会覆盖该语句命名的所有帐户的全局策略。

    • 要将两种类型的重用限制结合使用,请将PASSWORD HISTORYPASSWORD REUSE INTERVAL一起使用:

      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.user行均指示是否存在特定于帐户的设置,需要对当前密码进行验证以进行密码更改尝试。该设置是通过 nd 语句的PASSWORD REQUIRE选项建立的:CREATE USERALTER USER

    • 如果帐户设置为PASSWORD REQUIRE CURRENT,则密码更改必须指定当前密码。
    • 如果帐户设置为PASSWORD REQUIRE CURRENT OPTIONAL,则密码更改可能但不必指定当前密码。
    • 如果帐户设置为PASSWORD REQUIRE CURRENT DEFAULT,则password_require_current系统变量将确定该帐户的验证要求策略:

      • 如果password_require_current启用,密码更改必须指定当前密码。
      • 如果password_require_current禁用,则密码更改可能但不必指定当前密码。

    换句话说,如果帐户设置不是PASSWORD REQUIRE CURRENT DEFAULT,则帐户设置优先于password_require_current系统变量建立的全局策略。否则,该帐户将遵照该password_require_current设置。

    默认情况下,密码验证是可选的:password_require_current已禁用,并且没有PASSWORD REQUIRE选项的帐户创建默认为PASSWORD REQUIRE CURRENT DEFAULT

    下表显示了每个帐户设置如何与password_require_current系统变量值交互以确定帐户密码验证所需的策略。

    表6.10密码验证策略

    按帐户设置password_require_current系统变量密码更改需要当前密码吗?
    PASSWORD REQUIRE CURRENTOFF
    PASSWORD REQUIRE CURRENTON
    PASSWORD REQUIRE CURRENT OPTIONALOFF没有
    PASSWORD REQUIRE CURRENT OPTIONALON没有
    PASSWORD REQUIRE CURRENT DEFAULTOFF没有
    PASSWORD REQUIRE CURRENT DEFAULTON

    注意

    特权用户可以在不指定当前密码的情况下更改任何帐户密码,而不管验证要求的策略如何。特权用户是一个谁拥有全球的CREATE USER特权或UPDATE为特权mysql系统数据库。

    要全局建立密码验证策略,请使用password_require_current系统变量。其默认值为OFF,因此不需要更改帐户密码即可指定当前密码。

    例子:

    • 要建立密码更改必须指定当前密码的全局策略,请在服务器my.cnf文件中使用以下几行来启动服务器:

      [mysqld]
      password_require_current=ON
      
    • password_require_current在运行时设置并持久保存,请使用以下语句之一:

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

      SET PERSIST设置正在运行的MySQL实例的值。它还保存了用于后续服务器重新启动的值。请参见“变量分配的SET语法”。要更改正在运行的MySQL实例的值而不保存该值以供以后重新启动,请使用GLOBAL关键字而不是PERSIST

    要求全局密码验证的策略适用于尚未设置为覆盖该策略的所有帐户。要为单个帐户建立政策,请使用和语句的PASSWORD REQUIRE选项。请参见“ CREATE USER语句”和“ ALTER USER语句”。CREATE USERALTER USER

    特定于帐户的语句示例:

    • 要求更改密码指定当前密码:

      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 USERSET PASSWORD语句更改密码时,对当前密码进行验证。实例使用ALTER USER,而不是,这是首选的SET PASSWORD,但是此处描述的原理对于两种陈述都是相同的。

    在密码更改语句中,一个REPLACE子句指定了要替换的当前密码。例子:

    • 更改当前用户的密码:

      ALTER USER USER() IDENTIFIED BY ' uth_string' REPLACE 'current_auth_string';
      
    • 更改命名用户的密码:

      ALTER USER 'jeffrey'@'localhost'
      IDENTIFIED BY ' uth_string'
      REPLACE 'current_auth_string';
      
    • 更改命名用户的身份验证插件和密码:

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

    REPLACE子句的工作方式如下:

    • REPLACE如果需要更改帐户密码以指定当前密码,则必须提供该密码,以验证尝试进行更改的用户实际上知道当前密码。
    • REPLACE如果帐户的密码更改可能但不需要指定当前密码,则为可选。
    • 如果REPLACE指定,则必须指定正确的当前密码,否则会发生错误。即使REPLACE是可选的,也是如此。
    • REPLACE仅在更改当前用户的帐户密码时可以指定。(这意味着,在刚刚显示的示例中,jeffrey除非当前用户为,否则显式命名该帐户的语句将失败jeffrey。)即使特权用户尝试对另一个用户进行更改,也是如此。但是,这样的用户无需指定即可更改任何密码REPLACE
    • REPLACE为避免向其写入明文密码,二进制日志中将省略该符号。

    双密码支持

    从MySQL 8.0.14开始,允许用户帐户具有双重密码,分别指定为主要和次要密码。双密码功能使得可以在以下情况下无缝执行凭据更改:

    • 系统具有大量的MySQL服务器,可能涉及复制。
    • 多个应用程序连接到不同的MySQL服务器。
    • 必须对应用程序用来连接到服务器的一个或多个帐户进行定期的凭据更改。

    考虑仅在一个帐户只允许使用一个密码的情况下,在上述类型的方案中必须如何执行凭证更改。在这种情况下,在更改帐户密码并将其传播到所有服务器以及何时更新所有使用该帐户的应用程序以使用新密码的时间上,必须紧密合作。此过程可能涉及服务器或应用程序不可用的停机时间。

    使用双重密码,可以更容易地,分阶段地更轻松地进行凭据更改,而无需密切合作,也无需停机:

    1. 对于每个受影响的帐户,在服务器上建立一个新的主密码,并保留当前密码作为辅助密码。这使服务器可以识别每个帐户的主密码或辅助密码,而应用程序可以继续使用与以前相同的密码(现在是辅助密码)连接到服务器。
    2. 密码更改传播到所有服务器之后,修改使用任何受影响帐户的应用程序以使用帐户主密码进行连接。
    3. 将所有应用程序从辅助密码迁移到主要密码后,不再需要辅助密码,可以将其丢弃。此更改传播到所有服务器后,只能使用每个帐户的主密码进行连接。凭据更改现已完成。

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

    • 当您分配新的主密码时RETAIN CURRENT PASSWORDALTER USER nd SET PASSWORD语句的子句会将帐户当前密码保存为其次密码。
    • DISCARD OLD PASSWORD子句用于ALTER USER丢弃帐户辅助密码,仅保留主密码。

    假设对于先前描述的凭据更改方案,'appuser1'@'host1.example.com'应用程序使用一个名为的帐户来连接到服务器,并且该帐户的密码将从更改为。'password_ ''password_b'

    要执行此凭据更改,请使用ALTER USER以下命令:

    1. 在不是复制从属服务器的每个服务器上,将其设置为新的主密码,并保留当前密码作为辅助密码:'password_b' ppuser1

      ALTER USER 'appuser1'@'host1.example.com'
      IDENTIFIED BY 'password_b'
      RETAIN CURRENT PASSWORD;
      
    2. 等待密码更改,以将整个系统复制到所有从属服务器。
    3. 修改使用该 ppuser1帐户的每个应用程序,以使其使用密码而不是连接到服务器。'password_b''password_ '
    4. 此时,不再需要辅助密码。在不是复制从属服务器的每个服务器上,放弃辅助密码:

      ALTER USER 'appuser1'@'host1.example.com'
      DISCARD OLD PASSWORD;
      
    5. 丢弃密码更改复制到所有从属服务器后,凭据更改完成。

    RETAIN CURRENT PASSWORDDISCARD OLD PASSWORD条款具有以下效果:

    • RETAIN CURRENT PASSWORD保留帐户当前密码作为其辅助密码,以替换任何现有的辅助密码。新密码成为主密码,但是客户端可以使用主密码或辅助密码使用该帐户连接到服务器。(例外:如果ALTER USER or SET PASSWORD语句指定的新密码为空,则即使提供了辅助密码,辅助密码也将变为空RETAIN CURRENT PASSWORD。)
    • 如果您指定RETAIN CURRENT PASSWORD的主密码为空,则该语句将失败。
    • 如果帐户具有辅助密码,并且您在未指定RETAIN CURRENT PASSWORD的情况下更改了其主密码,则辅助密码将保持不变。
    • 对于ALTER USER,如果您更改分配给该帐户的身份验证插件,则辅助密码将被丢弃。如果更改身份验证插件并指定RETAIN CURRENT PASSWORD,则该语句将失败。
    • 对于ALTER USERDISCARD OLD PASSWORD如果存在辅助密码,则将其丢弃。该帐户仅保留其主密码,并且客户端只能使用该主密码来使用该帐户连接到服务器。

    修改辅助密码的语句需要以下特权:

    • APPLICATION_PASSWORD_ADMIN权限才能使用RETAIN CURRENT PASSWORDDISCARD OLD PASSWORD子句ALTER USER,并SET PASSWORD应用到自己的帐户报表。由于大多数用户仅需要一个密码,因此需要特权来操作您自己的辅助密码。
    • 如果要允许一个帐户操作所有帐户的辅助密码,则应授予该CREATE USER特权而不是APPLICATION_PASSWORD_ADMIN

    随机密码生成

    如MySQL的8.0.18,所述的CREATE USERALTER USERSET PASSWORD语句具有生成用于用户帐户的随机密码,作为替代,需要明确的管理员指定的文字的密码的能力。有关语法的详细信息,请参见每个语句的描述。本节描述了生成随机密码的共同特征。

    默认情况下,生成的随机密码的长度为20个字符。该长度由generated_random_password_length系统变量控制,范围为5到255。

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

    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  |
    +------	+-------	+----------------------	+
    

    CREATE USERALTER USERSET PASSWORD产生用于帐户的随机密码语句写入二进制日志作为CREATE USERALTER USER语句用,子句,其中是帐户认证插件和是帐户密码散列值。IDENTIFIED WITH uth_plugin AS ' uth_string' uth_plugin' uth_string'

    如果validate_password安装了该组件,则该组件实施的策略对生成的密码无效。(密码验证的目的是帮助人们创建更好的密码。)

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

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

    在这种情况下,“登录失败”表示客户端在连接尝试期间无法提供正确的密码。它不包括由于未知用户或网络问题等原因导致的连接失败。对于具有双重密码的帐户(请参阅“双重密码支持”),这两个帐户密码均视为正确。

    可以使用和语句的FAILED_LOGIN_ATTEMPTSPASSWORD_LOCK_TIME选项为每个帐户配置所需的登录失败次数和锁定时间。例子:CREATE USERALTER USER

    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.
    

    使用以下选项:

    • FAILED_LOGIN_ATTEMPTS N

      此选项指示是否跟踪指定错误密码的帐户登录尝试。该数字N指定连续多少个错误密码会导致临时帐户锁定。

    • PASSWORD_LOCK_TIME{N| UNBOUNDED}

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

    N每个选项的允许值范围是0到32767。值为0将禁用该选项。

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

    • 要使帐户发生登录失败跟踪和临时锁定,其FAILED_LOGIN_ATTEMPTSPASSWORD_LOCK_TIME选项都必须为非零。
    • 对于CREATE USER,如果FAILED_LOGIN_ATTEMPTS还是PASSWORD_LOCK_TIME没有指定,其隐含的默认值是0针对语句指定的所有账户。这意味着将禁用登录失败跟踪和临时帐户锁定。(这些隐式默认值也适用于引入失败登录跟踪之前创建的帐户。)
    • 对于ALTER USER,如果FAILED_LOGIN_ATTEMPTS还是PASSWORD_LOCK_TIME没有指定,它的价值仍然是由语句指定的所有账户不变。
    • 为了使临时帐户锁定,密码失败必须是连续的。在达到FAILED_LOGIN_ATTEMPTS失败登录值之前发生的任何成功登录都会导致失败计数重置。例如,如果FAILED_LOGIN_ATTEMPTS为4且发生了三个连续的密码失败,则必须再发生一次失败才能开始锁定。但是,如果下一次登录成功,则将重置该帐户的失败登录计数,以便再次需要四次连续失败才能锁定。
    • 一旦开始临时锁定,即使使用了正确的密码,也无法成功登录,直到锁定持续时间过去或通过以下讨论中列出的一种帐户重置方法将帐户解锁。

    当服务器读取授权表时,它将初始化每个帐户的状态信息,其中包括是否启用了失败登录跟踪,该帐户当前是否被临时锁定以及是否已开始锁定(如果已启用)以及该帐户发生临时锁定之前的失败次数未锁定。

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

    • 在以下任何情况下,都会对所有帐户进行全局重置:

      • 服务器重新启动。
      • 执行FLUSH PRIVILEGES。(启动服务器--skip-grant-tables会导致不读取授权表,这将禁用失败登录跟踪。在这种情况下,首次执行FLUSH PRIVILEGES会导致服务器读取授权表并启用失败登录跟踪,除了重置所有帐户)
    • 在以下任何一种情况下都会发生按帐户重置:

      • 登录帐户成功。
      • 锁定持续时间过去了。在这种情况下,失败登录计数将在下一次尝试登录时重置。
      • 执行ALTER USER将任何一个FAILED_LOGIN_ATTEMPTSPASSWORD_LOCK_TIME(或两个)设置为任何值(包括当前期权价值)ALTER USER ... UNLOCK的帐户对帐单,或执行该帐户对帐单。

        ALTER USER该帐户的其他语句对其当前的失败登录计数或锁定状态没有影响。

    登录失败跟踪与用于检查凭据的登录帐户相关联。如果正在使用用户代理,则会对代理用户(而不是代理用户)进行跟踪。也就是说,跟踪绑定到所指示的帐户USER(),而不是所指示的帐户CURRENT_USER()。有关代理和代理用户之间区别的信息,请参见“代理用户”。


    服务器处理过期的密码

    MySQL提供了密码过期功能,该功能使数据库管理员可以要求用户重置密码。密码可以根据自动过期策略手动过期(请)。

    ALTER USER语句启用帐户密码到期。例如:

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

    对于每个使用具有过期密码的帐户的连接,服务器要么断开客户端的连接,要么将客户端限制为“沙箱模式”,在该模式下,服务器允许客户端仅执行重置过期密码所需的那些操作。服务器采取哪种操作取决于客户端和服务器设置,这将在后面讨论。

    如果服务器断开客户端的连接,则返回ER_MUST_CHANGE_PASSWORD_LOGIN错误:

    shell>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或重置帐户密码SET PASSWORD。完成此操作后,服务器将恢复该会话以及使用该帐户的后续连接的正常访问。

      注意

      尽管可以通过将过期的密码设置为当前值来“重置”它,但出于良好的政策考虑,最好选择其他密码。DBA可以通过建立适当的密码重用策略来强制不重用。请参阅密码重用策略。

    • 客户端可以使用该SET语句。

    对于会话中不允许的任何操作,服务器将返回ER_MUST_CHANGE_PASSWORD错误:

    mysql> USE performance_schem ;
    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客户端的非交互式调用(例如,以批处理方式),如果密码过期,则服务器通常会断开与客户端的连接。要允许非交互式mysql调用保持连接状态,以便可以更改密码(使用沙箱模式中允许的语句),请--connect-expired-passwordmysql命令中添加该选项。

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

    注意

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

    在客户端,给定的客户端指示它是否可以处理过期密码的沙箱模式。对于使用C客户端库的客户端,有两种方法可以执行此操作:

    • 在连接之前将MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS标志传递mysql_options()给:

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

      这是mysql客户端中使用的技术,MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS如果以交互方式或通过--connect-expired-password选项调用,则启用该技术。

    • 在连接时将CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS标志传递给mysql_real_connect()

      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_password系统变量的值:

    • 如果disconnect_on_expired_password启用(默认值),则服务器会断开连接,并显示ER_MUST_CHANGE_PASSWORD_LOGIN错误消息。
    • 如果disconnect_on_expired_password禁用此选项,则服务器会将客户端置于沙盒模式。