MySQL 密码管理

MySQL 密码管理

支持的功能

MySQL 使用 validate_password 组件实现这些功能。

  • 密码到期更改密码

  • 密码重用限制,阻止重用旧密码

  • 密码验证

  • 双密码

    • 除了主要密码,还有一个第二密码 (辅助密码)
  • 密码强度评估,要求使用强密码

  • 生成随机密码

  • 密码错误跟踪,多次登陆失败会被临时锁定

内部与外部凭证存储

帐户凭证保存在系统表中

  • mysql.user

内部身份验证插件

  • mysql_native_password
  • (默认) caching_sha2_password
  • sha256_password

密码过期策略

密码自动过期策略

  • 系统变量

    • default_password_lifetime=N
      • 密码过期时间,单位天。
      • 这个变量用于设置全局策略。默认为0,表示密码永不过期。
  • 设置
    • 修改配置文件 /etc/my.cnf
      [mysqld]
      default_password_lifetime=180
      # default_password_lifetime=0  # 密码永不过期
      
    • 动态持久化设置
      SET PERSIST default_password_lifetime = 180;
      SET PERSIST default_password_lifetime = 0;
      

手动使密码过期

mysql> alter user zabbix@localhost password expire;
  • 语法

    这种方法会覆盖全局策略。

    ALTER|CREATE USER ... PASSWORD EXPIRE {INTERVAL N DAY|NEVER|DEFAULT}
    
  • 示例
    • 设置密码过期时间
      mysql> create user zabbix@localhost password expire interval 90 day;
      mysql> alter user zabbix@localhost password expire interval 90 day;
      
    • 设置密码永不过期
      mysql> create user zabbix@localhost password expire never;
      mysql> alter user zabbix@localhost password expire never;
      
    • 设置全局密码过期策略
      mysql> create user zabbix@localhost password expire default;
      mysql> alter user zabbix@localhost password expire default;
      

密码重用策略

密码历史

  • 限制从密码历史记录中选择新密码
  • 空密码不记录在密码历史中,并且任何时候都拒绝重用

可以增加限制

  • 基于密码更改次数
    • 新密码不能与最近使用的 N 个密码相同
  • 基于过去时间
    • 新密码不能最近 N 天使用过的密码相同

建立全局密码重用策略

  • 系统变量
    • password_history=N
      • 新密码不能与最近使用的 N 个密码相同
    • password_reuse_interval=N
      • 新密码不能最近 N 天使用过的密码相同
  • 配置
    • 修改配置文件 /etc/my.cnf
      [mysqld]
      password_history=6
      password_reuse_interval=365
      
    • 动态持久化设置
      SET PERSIST password_history = 6;
      SET PERSIST password_reuse_interval = 365;
      

为单个账户设置密码重用策略

  • 语法

    单独策略会覆盖全局策略。

    CREATE | ALTER USER ... {PASSWORD HISTORY N | PASSWORD REUSE INTERVAL N DAY}
    
    • PASSWORD HISTORY N
    • PASSWORD REUSE INTERVAL N DAY
  • 示例
    • 新密码不能与最近使用的5个密码相同
      mysql> create user zabbix@localhost password history 5;
      mysql> alter user zabbix@localhost password history 5;
      
    • 新密码不能与最近365天使用过得密码相同
      mysql> create user zabbix@localhost password reuse interval 365 day;
      mysql> alter user zabbix@localhost password reuse interval 365 day;
      
    • 合并设置
      mysql> create user zabbix@localhost password history 5 password reuse interval 365 day;
      mysql> alter user zabbix@localhost password history 5 password reuse interval 365 day;
      
    • 恢复全局默认设置
      mysql> create user zabbix@localhost password history default password reuse interval default;
      mysql> alter user zabbix@localhost password history default password reuse interval default;
      

密码验证策略

所谓密码验证,就是当更改账户密码时,需要提供当前密码。密码验证策略的数据保存在 mysql.user 系统表中。

设置全局密码验证策略

  • 系统变量
    • default_authentication_plugin
      • 默认的身份验证插件
    • password_require_current
      • 密码验证策略,是否需要指定当前密码。默认禁用
      • 拥有 CREATE USER 全局权限或者对 mysql 库有 UPDATE 权限的账户,可以无视密码验证策略,不需要指定当前密码
  • 配置
    • 修改配置文件 /etc/my.cnf
      [mysqld]
      password_require_current=ON
      
    • 动态持久化设置
      SET PERSIST password_require_current = ON;
      SET PERSIST password_require_current = OFF;
      

为单个账户设置密码验证策略

  • 语法
    CREATE | ALTER USER ... PASSWORD REQUIRE CURRENT {OPTIONAL | DEFAULT}
    
    • CURRENT
      • 需要指定当前密码
    • CURRENT OPTIONAL
      • 不需要指定当前密码
    • CURRENT DEFAULT
      • 使用全局设置
      • 如果不指定 CURRENT 后面的选项,默认设置为 PASSWORD REQUIRE CURRENT DEFAULT
  • 示例
    • 设置需要指定当前密码
      mysql> create user zabbix@localhost password require current;
      mysql> alter user zabbix@localhost password require current;
      
    • 设置不需要指定当前密码
      mysql> create user zabbix@localhost password require current optional;
      mysql> alter user zabbix@localhost password require current optional;
      
    • 恢复全局验证策略
      mysql> create user zabbix@localhost password require current default;
      mysql> alter user zabbix@localhost password require current default;
      

修改密码

  • 语法
    ALTER USER xxx IDENTIFIED BY 'auth_string' REPLACE 'current_auth_string';
    

    Note: SET PASSWORD 用法类似。

    • 如果在修改密码时,需要指定当前密码,必须使用 REPLACE
    • 如果在修改密码时,不需要指定当前密码, REPLACE 是可选的
    • 如果使用了 REPLACE,则必须指定正确的当前密码,否则报错
    • 只有更改当前账户的密码时,才能指定 REPLACE
    • 在二进制日志中,REPLACE 会被忽略,以避免写入纯文本密码
  • 示例
    • 修改当前账户密码
      mysql> alter user user() identified by 'zabbix1' replace 'zabbix';
      mysql> alter user u_zabbix@localhost identified by 'zabbix2' replace 'zabbix1';
      
      • 这里的账户必须是当前账户,否则报错。
        mysql> alter user zabbix@localhost identified by 'zabbix' replace 'zabbix';
        ERROR 3893 (HY000): Do not specify the current password while changing it for other users.
        
    • 修改当前账户的验证插件和密码
      mysql> alter user u_zabbix@localhost identified with caching_sha2_password by 'zabbix3' replace 'zabbix1';
      Query OK, 0 rows affected (0.02 sec)
      

      Note: 这里的账户必须是当前账户,否则报错。更改插件需要 CREATE USER 权限。

      mysql> alter user u_zabbix@localhost identified with caching_sha2_password by 'zabbix3' replace 'zabbix2';
      ERROR 1227 (42000): Access denied; you need (at least one of) the CREATE USER privilege(s) for this operation
      

双密码支持

允许账户具有双密码,一个主要密码,一个次要密码。

如果只有一个密码,在以下场景下,在更改密码时,会造成服务中断:

  • 系统存在大量 MySQL 服务器,可能涉及复制
  • 多个应用程序连接到不同的 MySQL 服务器
  • 应用程序的账户需要定期更改用户凭证

双密码时,可以设置一个新的密码作为主密码,保留原来的密码作为第二密码。在所有服务器完成修改密码之后,可以让应用程序切换到主密码。全部切换完毕后,第二密码可以删掉。

语法

  • 将当前密码保留为第二密码
    ALTER USER|SET PASSWORD ... RETAIN CURRENT PASSWORD
    

    Note: 这个语句是将当前密码置为第二密码,将新赋予的密码作为了主密码。

    • 如果账户已存在第二密码,会替换它
    • 如果新密码是空密码,第二密码也会变为空密码
    • 如果这个账户之前的密码就是空密码,执行时会报错
    • 如果 ALTER USER 同时更改认证插件,第二密码会被丢弃;如果还指定了 RETAIN CURRENT PASSWORD,则语句会报错
    • 所需权限
      • APPLICATION_PASSWORD_ADMIN
        • 可以操纵自己账户的密码
      • CREATE USER
        • 可以操纵其他账户的密码
  • 删除账户的第二密码,只保留主密码
    ALTER USER ... DISCARD OLD PASSWORD
    

查看第二密码

  • mysql.user
    • User_attributes 列
      mysql> select * from mysql.user where user='zabbix'\G
      *************************** 1. row ***************************
                          Host: localhost
                          User: zabbix
      ...
                        plugin: caching_sha2_password
         authentication_string: A005j2QMF.=,Wf RU|Z8ibaO9hZw0a02fP4FZWANm8dZnGoR34c81hL1eU3d736
      ...
               User_attributes: {"additional_password": "A005q\u0019g{X7F\"he^lKw;\u0010:WI\u0011uTk6m1SpCF5zJocAOrU8qtvBt5p7FY/8Zye8DpkK.O9"}
      

配置过程

  • 主节点创建新密码,同时将当前密码保留为第二密码
    mysql> alter user zabbix@localhost identified by '123' retain current password;
    
  • 等待从节点的密码复制完成

  • 将复制结构的密码修改为新密码

  • 丢弃第二密码 (旧密码)

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

随机生成密码

随机密码的特点

  • 默认是20位长度

  • 存储在 myql.user 系统表中,生成的随机密码保存在 generated_password 列

  • 在二进制日志中的记录格式

    CREATE | ALTER USER ... IDENTIFIED WITH auth_plugin AS 'auth_string'
    
    • 密码做 hash 处理
  • 如果安装了 validate_password 组件,则它的策略对生成随机密码无影响

系统变量

  • generated_random_password_length

    • 控制随机密码长度
    • 范围是 5-255,默认20

语法

CREATE USER xxx IDENTIFIED BY RANDOM PASSWORD;
ALTER USER xxx IDENTIFIED BY RANDOM PASSWORD;
SET PASSWORD FOR xxx TO RANDOM;
  • 示例
    mysql> create user
    u1@localhost identified by random password, 
    u2@localhost identified by random password, 
    u3@localhost identified by random password;
    +------+-----------+----------------------+
    | user | host      | generated password   |
    +------+-----------+----------------------+
    | u1   | localhost | tJ31>9FU89[@OxQ8djRa |
    | u2   | localhost | bHbzWJ,}Xb+:)[.c]w:X |
    | u3   | localhost | w}Z}VrOjO4UPlgX@OSX] |
    +------+-----------+----------------------+

    mysql> alter user
    u1@localhost identified by random password,
    u2@localhost identified by random password;
    +------+-----------+----------------------+
    | user | host      | generated password   |
    +------+-----------+----------------------+
    | u1   | localhost | Gze0ox)%;9O@Q!3cK&Ei |
    | u2   | localhost | 7L_fD!->Vc4OjuQimRb) |
    +------+-----------+----------------------+

    mysql> set password for u3@localhost to random;
    +------+-----------+----------------------+
    | user | host      | generated password   |
    +------+-----------+----------------------+
    | u3   | localhost | cGe7e,:]!d&7C9:++z<] |
    +------+-----------+----------------------+

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

连续登录失败 (密码错误) 一定次数,会导致账户临时锁定。

语法

mysql> create user u1@localhost identified by 'u1' failed_login_attempts 3 password_lock_time 3;
mysql> create user u2@localhost identified by 'u2' failed_login_attempts 4 password_lock_time unbounded;
  • FAILED_LOGIN_ATTEMPTS N
    • 连续 N 次登录失败
  • PASSWORD_LOCK_TIME {N | UNBOUNDED}
    • 锁定时间。
    • N 天,N 的范围是 0-32767。
    • 0表示禁用;UNBOUNDED 表示一直锁定

特点

  • FAILED_LOGIN_ATTEMPTS 和 PASSWORD_LOCK_TIME 必须非0
  • 如果 CREATE USER 未指定这两个选项,选项值默认是0
  • 必须是连续登录失败,如果中间成功了一次,这个连续失败次数会重置
  • 一旦发生锁定,后续就无法再次登录,除非解锁
  • 如果使用了代理用户,失败跟踪的是代理用户,而不是被代理用户

重置账户状态 (解除临时锁定)

  • 全局重置
    • 服务器重启

    • 刷新权限

      mysql> flush privileges;
      
  • 单个账户重置
    • 等待锁定时间结束

    • 重新设置登录失败次数和锁定时间

      mysql> alter user u1@localhost failed_login_attempts 3 password_lock_time 3;
      
    • 正常的账户解锁
      mysql> alter user u1@localhost account unlock;
      

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注