必须用 ALTER USER ... PASSWORD EXPIRE,SET PASSWORD 无效且只对新登录生效;因 SET PASSWORD 仅更新 authentication_string 而不设置 password_expired 字段,而 MySQL 强制改密依赖 password_expired 元数据驱动。
必须用 ALTER USER ... PASSWORD EXPIRE,SET PASSWORD 无效,且只对新登录生效。
SET PASSWORD FOR 'u'@'h' = 'xxx' 只更新 authentication_string 字段,完全不碰 password_expired。MySQL 的强制改密逻辑是元数据驱动的——只要 password_expired 是 'N',哪怕密码刚设完,登录后照样能执行 SELECT。
SET PASSWORD FOR 'alice'@'localhost' = 'new123'; ALTER USER 'alice'@'localhost' PASSWORD EXPIRE; —— 两步分离,第二步容易漏ALTER USER 'alice'@'localhost' IDENTIFIED BY 'new123' PASSWORD EXPIRE;
ALTER USER 'alice'@'localhost' PASSWORD EXPIRE;,别混用 IDENTIFIED BY
命令跑成功 ≠ 生效。以下任一不满足,PASSWORD EXPIRE 就是摆设:
SELECT user, host FROM mysql.user WHERE user = 'alice';
ALTER USER 权限(不是 UPDATE 权限)SELECT @@default_password_lifetime; 不能为 0;若为 0,全局禁用过期机制,所有 PASSWORD EXPIRE 都失效设了 PASSWORD EXPIRE 却还能正常执行 SELECT,大概率是:
SELECT @@default_password_lifetime; 返回 0
SET NAMES utf8mb4 等语句,但还没发第一条非 SET 类语句——ERROR 1820 要等到首个非 SET 语句才触发两者都把 password_expired 设为 'Y',但后续行为不同:
PASSWORD EXPIRE NOW:下次登录认证成功后,首次执行非 SET 语句就报错PASSWORD EXPIRE INTERVAL 60 DAY:从 password_last_changed 时间起算 60 天;若当前已超期,效果等同于 NOW
password_expired 字段:SELECT user, host, password_last_changed, TIMESTAMPADD(DAY, @@default_password_lifetime, password_last_changed) AS expires_at FROM mysql.user WHERE user = 'alice';
最容易被忽略的是:过期状态在服务端认证后、授权前就返回错误,根本不会走到 SQL 执行阶段——所以没法用 mysql -u alice -p 交互式输入绕过,也没法在连接池里“先连再处理”。