MySQL 8.0+ 真锁定账号必须显式设置 FAILED_LOGIN_ATTEMPTS 和 PASSWORD_LOCK_TIME,并使用 caching_sha2_password 或 mysql_native_password 插件;仅靠 connection_control 插件只能延迟响应,无法真正锁定账号。

MySQL 8.0+ 真锁定账号只靠 FAILED_LOGIN_ATTEMPTS 和 PASSWORD_LOCK_TIME
MySQL 8.0+ 要实现“输错密码后账号真正被锁、后续登录直接拒绝”,唯一有效路径是:在创建或修改用户时显式声明 FAILED_LOGIN_ATTEMPTS 和 PASSWORD_LOCK_TIME,且该用户必须使用 caching_sha2_password 或 mysql_native_password 认证插件。其他方式——比如只装 connection_control 插件——只会加延迟,不改 account_locked 字段,不算真锁定。
-
FAILED_LOGIN_ATTEMPTS 5表示第 5 次失败后触发锁定(不是“累计到 5 次”,而是连续失败计数,成功登录会重置) -
PASSWORD_LOCK_TIME 30单位是**天**(不是分钟!),若设为0则永久锁定,到期不会自动恢复,必须有一次成功登录才清除account_locked = 'Y' - 策略按
'user'@'host'组合独立生效,'u'@'192.168.1.10'和'u'@'192.168.1.11'的失败次数互不干扰 - 不生效的常见原因:用户认证插件不是上述两种之一;没在
CREATE USER或ALTER USER中显式写这两个参数;validate_password插件未启用(虽非硬依赖,但等保常要求启用)
怎么确认账号到底锁没锁?别信错误提示
输错密码和账号被锁,MySQL 都报 ERROR 1045 (28000),根本没法区分。唯一可靠方式是查系统表:
SELECT user, host, account_locked, failed_login_attempts FROM mysql.user WHERE user = 'u';
- 如果
account_locked = 'Y'→ 真被锁了,后续连接连认证流程都不走 - 如果
failed_login_attempts > 0但account_locked = 'N'→ 还在累积失败次数,未达阈值 -
failed_login_attempts是内部计数器,仅当用户用支持的认证插件登录失败时才会更新
connection_control 插件只能拖慢攻击,不能锁账号
它只是让第 N 次失败后的响应变慢,不拦截连接请求,也不改 account_locked 字段。所有失败都返回同样错误,客户端无法感知延迟机制存在。
- 必须同时加载两个插件:
connection_control.so和connection_control_failed_login_attempts.so,缺一不可 -
connection_control_failed_connections_threshold = 3表示“从第 4 次失败开始加延迟”,但若connection_control_min_connection_delay = 0(默认值),延迟就是 0 毫秒 → 完全无感 - 单位是毫秒,不是秒:
60000是 1 分钟,60是 60 毫秒,基本察觉不到 - 对 socket 连接失败、用户不存在、SSL 错误、网络超时等均不生效,只统计标准密码认证失败
解锁只能手动,且注意策略绑定细节
被 FAILED_LOGIN_ATTEMPTS 触发的锁定,到期不会自动解除(除非设了正数天数且时间到了),必须由管理员执行:
ALTER USER 'u'@'%' ACCOUNT UNLOCK;
-
ALTER USER ... ACCOUNT LOCK是手动锁,和失败触发的自动锁无关,两者状态字段都是account_locked,但触发逻辑完全不同 - 修改已有用户的锁定策略,必须用
ALTER USER重新声明完整参数,比如只改PASSWORD_LOCK_TIME不带FAILED_LOGIN_ATTEMPTS,旧的失败计数可能保留但新策略不生效 - 最易忽略的点:策略生效的前提是用户创建/修改时绑定了正确认证插件,例如:
CREATE USER 'u'@'%' IDENTIFIED WITH caching_sha2_password BY 'pwd' FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 1;


















