mysql 8.0+账户锁定策略需同时满足三条件才生效:认证插件为caching_sha2_password或mysql_native_password、failed_login_attempts与password_lock_time成对设置、validate_password插件已启用;缺一则account_locked恒为n。

MySQL 8.0+ 原生账户锁定策略不会自动生效,必须同时满足三个硬性条件:用户认证插件是 caching_sha2_password 或 mysql_native_password、FAILED_LOGIN_ATTEMPTS 和 PASSWORD_LOCK_TIME 成对设置、validate_password 插件已启用——缺一不可,否则查 account_locked 字段永远是 N。
为什么 ALTER USER FAILED_LOGIN_ATTEMPTS 3 没反应?
这个命令单独执行会被 MySQL 静默忽略,不报错也不生效。它不是独立开关,而是策略绑定参数的一部分。
-
FAILED_LOGIN_ATTEMPTS和PASSWORD_LOCK_TIME必须同时出现在同一条CREATE USER或ALTER USER语句中,顺序无关,但少一个就完全失效 - 已有用户不能只加策略:必须连认证插件一起重置,例如
ALTER USER 'u'@'%' IDENTIFIED WITH caching_sha2_password BY 'pwd' FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 0.04167;(锁 1 小时) - 若用户当前插件是
auth_socket或sha256_password,即使语法写对,account_locked字段也始终为N
如何确认 validate_password 插件已真正启用?
该插件不是可选增强项,而是失败计数机制的底层依赖。没它,输错密码根本不会累加计数,日志里也不会出现 Too many failed login attempts 记录。
- 检查状态:
SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'validate_password';,结果必须是ACTIVE - 启用方式二选一:配置文件加
plugin_load_add = validate_password.so后重启;或运行INSTALL PLUGIN validate_password SONAME 'validate_password.so'; - 注意:启用后会强制触发密码强度校验(如
validate_password.length),可能让旧脚本建用户失败
为什么 max_connect_errors 不是防暴力破解的正确参数?
它统计的是「TCP 连接成功但认证数据没发完就断开」的次数,和密码输错无关。攻击者用标准 MySQL client 正常重试,这个值根本不会增加。
- 设成 1 并不能防爆破,反而容易因网络抖动误伤正常连接
- 一旦触发,MySQL 会把整个 IP 加入
host_cache并拒绝所有后续连接(包括密码正确的),恢复只能靠FLUSH HOSTS或重启 - 真正有效的前置防护是系统级:比如
fail2ban监控 error log 中的Access denied for user,匹配 5 次就封 IP 1 小时
PASSWORD_LOCK_TIME 单位是天,不是秒或分钟
这是最常写错的地方。写成 PASSWORD_LOCK_TIME 60 意味着锁 60 天,不是 60 秒。
- 锁 5 分钟:写
0.00347(5 ÷ 1440) - 锁 1 小时:写
0.04167(1 ÷ 24) -
PASSWORD_LOCK_TIME 0表示永久锁定,不是“不锁定”——必须由管理员手动执行ALTER USER 'u'@'%' ACCOUNT UNLOCK; - 锁定期满不会自动解锁:必须有一次成功登录,才会重置失败计数并清除锁定状态
别指望靠 MySQL 单层机制挡住暴力破解。账户锁定只是最后一道闸门,真正关键的是不让可疑连接进来——限制源 IP、关闭远程 root、禁用 socket 认证、用防火墙限频次,这些比调参重要得多。











