MySQL 8.0.19+ 密码重用限制需同时启用 validate_password 插件(policy=STRONG)、caching_sha2_password 插件、password_history 与 password_reuse_interval 双参数非零,并通过 ALTER USER ... PASSWORD HISTORY 显式声明用户级策略才生效。

MySQL 8.0 实现密码重用限制,不是配个 password_history 就完事——它必须和 password_reuse_interval 配对生效,且只在 ALTER USER ... IDENTIFIED BY 场景下触发校验。
确认 MySQL 版本和认证插件是否达标
低于 8.0.19 的版本压根不识别 password_history 变量,设了也白设。插件用错更隐蔽:哪怕版本够,若用户认证插件是 mysql_native_password,策略完全不触发,也不报错。
- 先查版本:
SELECT VERSION();—— 输出必须 ≥8.0.19 - 再查目标用户插件:
SELECT user, host, plugin FROM mysql.user WHERE user = 'your_user'; - 如果不是
caching_sha2_password或sha256_password,得先改插件:ALTER USER 'your_user'@'%' IDENTIFIED WITH caching_sha2_password BY 'xxx'; - 改完必须执行
FLUSH PRIVILEGES;,否则新插件不加载
必须同时设置两个参数,缺一不可
password_history 控制“最近几次不能重用”,password_reuse_interval 控制“多少天内不能重用”。MySQL 要求二者**同时非零**才激活整个策略。只设其中一个,等于没设。
- 错误做法:
SET PERSIST password_history = 5;(password_reuse_interval仍是默认的0)→ 策略不生效 - 正确组合示例:
SET PERSIST password_history = 5;和SET PERSIST password_reuse_interval = 90; - 单位全是“天”,不是秒或小时
- 值为
0表示禁用,不是“不限制”——这是最容易误解的点
全局设置 ≠ 用户生效,用户级声明才管用
SET PERSIST password_history = 5; 只影响后续新建的用户;对已有用户完全无效。很多运维改完全局变量,再去 phpMyAdmin 改密码,发现旧密码还能复用,就是卡在这儿。
- 真正起效的是用户级显式声明:
ALTER USER 'u1'@'%' PASSWORD HISTORY 5; - 必须带
PASSWORD HISTORY子句,只写IDENTIFIED BY不触发校验 - phpMyAdmin 图形界面底层调用的是
SET PASSWORD,绕过所有历史检查——建议禁用该入口 - 想让所有现有用户受控?只能逐个执行
ALTER USER ... PASSWORD HISTORY N;,没有批量命令
validate_password 插件不是可选,而是前提条件
从知识库多份资料交叉验证可知:password_history 和 password_reuse_interval 在 MySQL 8.0+ 中实际依赖 validate_password 插件,且仅在 policy = STRONG 模式下才真正启用。
- 先检查插件是否已装:
SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'validate_password'; - 未安装则执行:
INSTALL PLUGIN validate_password SONAME 'validate_password.so'; - 设策略等级:
SET GLOBAL validate_password.policy = STRONG;(注意:不是MEDIUM) - 然后才设历史参数:
SET GLOBAL validate_password.history = 5;和SET GLOBAL validate_password.reuse_interval = 90; - STRONG 模式还要求配置词典文件,否则可能报错
Plugin 'validate_password' could not be initialized
最常被忽略的其实是执行路径:策略只在校验 ALTER USER ... IDENTIFIED BY 时介入,而 UPDATE mysql.user、GRANT ... IDENTIFIED BY、mysqladmin password 全部绕过。别用错命令,也别指望重启后立刻对所有已有会话生效——它只约束下一次符合规范的密码修改动作。











