mysql 8.0+通过default_password_lifetime全局配置或alter user password expire命令启用密码过期策略,支持永不过期(设为0)、立即过期及指定天数过期;过期状态需结合password_expired字段与password_last_changed+default_password_lifetime计算判定。

MySQL 8.0+ 如何启用密码过期策略
MySQL 8.0 起原生支持密码过期控制,核心是通过 ALTER USER 设置 PASSWORD EXPIRE 属性,或全局配置 default_password_lifetime。低于 8.0 的版本不支持该机制,强行修改系统表或绕过验证属于高风险操作,不建议尝试。
实操建议:
- 启用全局策略:在
my.cnf的[mysqld]段添加default_password_lifetime = 90(单位为天),重启 MySQL 生效;设为0表示永不过期 - 对单个用户强制立即过期:
ALTER USER 'devuser'@'%' PASSWORD EXPIRE;,下次登录会报错Error 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement. - 设置用户特定过期时间:
ALTER USER 'admin'@'localhost' PASSWORD EXPIRE INTERVAL 60 DAY;
如何查看和确认密码是否已过期
密码过期状态不会直接显示在 SHOW CREATE USER 中,需查 mysql.user 表的 password_expired 字段(值为 'Y' 或 'N'),但注意:该字段仅反映“是否被显式设为过期”,不等同于“已超期”。真正判断是否超期依赖 password_last_changed 和 default_password_lifetime 计算。
实操建议:
- 查当前用户过期状态:
select user, host, password_expired, password_last_changed FROM mysql.user WHERE user = 'testuser'; - 查所有已过期(含显式过期 + 自动超期)的账号:
SELECT user, host, password_last_changed, TIMESTAMPADD(DAY, @@default_password_lifetime, password_last_changed) AS expires_at FROM mysql.user WHERE password_expired = 'Y' OR (password_last_changed IS NOT NULL AND @@default_password_lifetime > 0 AND TIMESTAMPADD(DAY, @@default_password_lifetime, password_last_changed)
密码过期后用户如何重置
过期用户首次登录时无法执行任何语句(包括 SELECT),必须先用 ALTER USER ... IDENTIFIED BY 修改密码。MySQL 不提供交互式提示或跳转页面,错误信息明确但容易被客户端忽略。
常见错误现象:
- 命令行登录后直接报
ERROR 1820,光标停留在空白行,无进一步提示 - 某些 ORM(如 django)连接池初始化失败,日志里只显示 “access denied”,实际根因是密码过期
- PHP 的
mysqli报mysqli_real_connect(): (HY000/1820),需捕获异常并引导重置
实操建议:
- dba 应提前导出即将过期账户列表,批量发送提醒邮件
- 应用部署前检查连接账户是否在过期窗口内,避免上线即中断
- 重置命令示例:
ALTER USER 'appuser'@'10.20.%' IDENTIFIED BY 'NewPass!2024';
与 validate_password 插件的协同使用
validate_password 插件控制密码强度,和过期策略独立但常共存。两者都启用时,用户重置密码必须同时满足长度、复杂度、历史记录(password_history)和过期时限要求,否则报 ERROR 1819 (HY000): Your password does not satisfy the current policy requirements.
关键点:
- 插件必须先安装:
INSTALL PLUGIN validate_password SONAME 'validate_password.so'; - 强度等级由
validate_password.policy控制(0=LOW,1=MEDIUM,2=STRONG),MEDIUM 要求至少 8 位 + 数字 + 大小写字母 + 特殊字符 - 若开启
validate_password.history = 5,新密码不能与最近 5 次密码重复——这点常被忽略,导致重置失败 - 插件配置项(如
validate_password.Length)需在my.cnf中设置并重启,运行时SET GLOBAL不生效
密码过期策略本身不加密传输、不防暴力破解,它只是账户生命周期管理的一环。真正容易被忽略的是:应用连接池复用过期连接、监控脚本用固定账户轮询、备份任务使用的低权限账号长期未更新——这些场景下,策略生效反而引发静默故障。