支持的功能
MySQL 使用 validate_password 组件实现这些功能。
- 密码到期更改密码
-
密码重用限制,阻止重用旧密码
-
密码验证
-
双密码
- 除了主要密码,还有一个第二密码 (辅助密码)
- 密码强度评估,要求使用强密码
-
生成随机密码
-
密码错误跟踪,多次登陆失败会被临时锁定
内部与外部凭证存储
帐户凭证保存在系统表中
- mysql.user
内部身份验证插件
- mysql_native_password
- (默认) caching_sha2_password
- sha256_password
密码过期策略
密码自动过期策略
-
系统变量
- default_password_lifetime=N
- 密码过期时间,单位天。
- 这个变量用于设置全局策略。默认为0,表示密码永不过期。
- default_password_lifetime=N
- 设置
- 修改配置文件 /etc/my.cnf
[mysqld] default_password_lifetime=180 # default_password_lifetime=0 # 密码永不过期
- 动态持久化设置
SET PERSIST default_password_lifetime = 180; SET PERSIST default_password_lifetime = 0;
- 修改配置文件 /etc/my.cnf
手动使密码过期
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 天使用过的密码相同
- password_history=N
- 配置
- 修改配置文件 /etc/my.cnf
[mysqld] password_history=6 password_reuse_interval=365
- 动态持久化设置
SET PERSIST password_history = 6; SET PERSIST password_reuse_interval = 365;
- 修改配置文件 /etc/my.cnf
为单个账户设置密码重用策略
- 语法
单独策略会覆盖全局策略。
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;
- 新密码不能与最近使用的5个密码相同
密码验证策略
所谓密码验证,就是当更改账户密码时,需要提供当前密码。密码验证策略的数据保存在 mysql.user 系统表中。
设置全局密码验证策略
- 系统变量
- default_authentication_plugin
- 默认的身份验证插件
- password_require_current
- 密码验证策略,是否需要指定当前密码。默认禁用
- 拥有 CREATE USER 全局权限或者对 mysql 库有 UPDATE 权限的账户,可以无视密码验证策略,不需要指定当前密码
- default_authentication_plugin
- 配置
- 修改配置文件 /etc/my.cnf
[mysqld] password_require_current=ON
- 动态持久化设置
SET PERSIST password_require_current = ON; SET PERSIST password_require_current = OFF;
- 修改配置文件 /etc/my.cnf
为单个账户设置密码验证策略
- 语法
CREATE | ALTER USER ... PASSWORD REQUIRE CURRENT {OPTIONAL | DEFAULT}
- CURRENT
- 需要指定当前密码
- CURRENT OPTIONAL
- 不需要指定当前密码
- CURRENT DEFAULT
- 使用全局设置
- 如果不指定 CURRENT 后面的选项,默认设置为 PASSWORD REQUIRE CURRENT DEFAULT
- CURRENT
- 示例
- 设置需要指定当前密码
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
- 可以操纵其他账户的密码
- APPLICATION_PASSWORD_ADMIN
- 删除账户的第二密码,只保留主密码
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"}
- User_attributes 列
配置过程
- 主节点创建新密码,同时将当前密码保留为第二密码
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;