alter user 是唯一能触发密码过期逻辑的方式;update mysql.user 或 set password 均无效;default_password_lifetime 仅影响新用户;validate_password 插件需手动启用并配置,且仅约束后续密码修改。

ALTER USER 是唯一能设置密码过期的方式
直接 UPDATE mysql.user 表或用 SET PASSWORD 修改密码,都不会触发过期逻辑——前者被 MySQL 忽略,后者只更新哈希值,不碰 password_expired、password_last_changed 等元数据字段。真实生效的只有 ALTER USER 语句。
常见操作包括:
-
ALTER USER 'app'@'%' PASSWORD EXPIRE INTERVAL 90 DAY;—— 90 天后强制改密 -
ALTER USER 'admin'@'localhost' PASSWORD EXPIRE;—— 立即过期,适合临时账号或安全审计后紧急锁定 -
ALTER USER 'svc'@'10.%.%.%' PASSWORD EXPIRE NEVER;—— 显式禁用,适用于连接池类服务账号(慎用)
注意:PASSWORD EXPIRE DEFAULT 不等于“不过期”,而是继承 @@default_password_lifetime 值,容易误判;host 必须完全匹配,'u'@'localhost' 和 'u'@'%' 是两个独立账户。
default_password_lifetime 只影响新用户
全局变量 default_password_lifetime 的作用非常有限:它仅决定后续新建用户的默认过期行为,对已有用户(包括刚重置过密码的 root)完全无效。生产环境常因忽略这点导致等保测评“部分账号未过期”被扣分。
设置方式有两种:
- 运行时:执行
SET PERSIST default_password_lifetime = 90;(推荐,自动写入mysqld-auto.cnf) - 配置文件:在
/etc/my.cnf的[mysqld]段添加default_password_lifetime = 90,然后重启mysqld
查当前值用:SELECT @@default_password_lifetime;。返回 0 表示永不过期(等保三级不合规),返回 NULL 表示交由用户级策略决定,并非“默认开启”。
validate_password 插件必须手动启用并配置策略
MySQL 8.0+ 默认内置 validate_password,但状态是 DISABLED。不启用,ALTER USER ... IDENTIFIED BY 就可能因弱密码报 ERROR 1819,这不是语法错误,是校验拦截。
启用与配置步骤:
- 检查是否已加载:
SHOW VARIABLES LIKE 'validate_password%'; - 若未启用,执行:
INSTALL PLUGIN validate_password SONAME 'validate_password.so'; - 设为强策略:
SET GLOBAL validate_password_policy = 'STRONG'; - 最小长度 12:
SET GLOBAL validate_password_length = 12;
验证效果:执行 ALTER USER 'test'@'%' IDENTIFIED BY '123456'; 应立即报错 ERROR 1819。注意:该插件对已有密码不做回溯检查,只约束后续修改行为。
验证策略是否真正落地,不能只看 mysql.user 表
查到 password_expired = 'Y' 不代表策略起效——MySQL 实际拦截需同时满足三个条件:用户无 ALTER USER 权限、@@default_password_lifetime > 0、连接未带 --init-command 类自动执行逻辑。
最简验证方式:
- 用目标账号登录:
mysql -u alice -p - 输完密码后**立刻**执行一条非
SET语句,如SELECT 1; - 若返回
ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.,才说明策略真正生效
此时唯一合法操作是:ALTER USER USER() IDENTIFIED BY 'newpass';。用 SET PASSWORD 或其他 DML/DDL 都会被拒。最容易被忽略的是:这个拦截发生在认证成功之后、首次非 SET 语句执行时,SET NAMES utf8mb4 这类仍能通过,容易误判为“没生效”。











