MySQL不支持禁止用户改自己密码,必须组合账户锁定、权限回收(撤CREATE USER和UPDATE ON mysql.user)及清理外部硬编码密码;REVOKE ALTER USER会报错因其非合法权限名。

MySQL 本身不支持直接禁止用户修改自己密码,没有 DENY ALTER USER 或类似权限开关。想合规落地,必须组合使用账户锁定、权限回收和外部凭证清理——少一步都可能被绕过。
为什么 REVOKE ALTER USER 会报错?
因为 ALTER USER 不是 MySQL 的合法权限名。执行 REVOKE ALTER USER ON *.* FROM 'u'@'h' 会直接报语法错误。真正起作用的是 CREATE USER 权限(它隐含修改自身认证信息的能力),以及全局 UPDATE 权限(可写 mysql.user 表)。检查当前权限用:
SHOW GRANTS FOR 'u'@'h';
重点看是否含以下任意一项:
CREATE USER ON *.*UPDATE ON mysql.user-
GRANT ALL PRIVILEGES ON *.*(隐含以上全部)
真正有效的权限回收操作
仅靠 REVOKE 不够,必须显式清除高危权限并验证结果:
- 撤掉创建用户能力:
REVOKE CREATE USER ON *.* FROM 'u'@'h' - 撤掉系统表写权限:
REVOKE UPDATE ON mysql.user FROM 'u'@'h'(注意不能写成mysql.*) - 确认没残留其他高危权限:
REVOKE INSERT, DELETE, DROP ON mysql.* FROM 'u'@'h' - 执行后重连,再跑一次
SHOW GRANTS FOR 'u'@'h'—— 如果还看到CREATE USER,说明该用户是通过角色继承的,得查mysql.role_edges并对对应角色也REVOKE
ACCOUNT LOCK 是最硬的兜底手段
权限回收后仍存在缓存或配置残留风险,ACCOUNT LOCK 能立即切断登录入口,且错误明确:
ALTER USER 'u'@'h' ACCOUNT LOCK;
后续任何连接都会返回:ERROR 3118 (HY000): Access denied for user 'u'@'h'. Account is locked. 这比改密码更可靠,因为:
- 不会触发
validate_password插件校验(避免因策略宽松导致新密码被接受) - 不依赖客户端是否缓存旧凭证(锁账户后连握手阶段就失败)
- 绕过所有 SQL 层权限判断,服务端直拒
别漏掉外部硬编码密码这个致命漏洞
即使数据库里锁死了,如果应用配置文件(如 application.yml、.env)或连接池(HikariCP/Druid)里还存着明文密码,攻击者拿到配置就能直连。必须同步做:
- 搜索所有代码仓库和部署目录,grep
password、authentication_string等关键词 - 确认连接池未启用自动重连 + 凭证缓存(例如 HikariCP 的
connection-init-sql若含SET PASSWORD就危险) - 程序类账号建议改用角色:建一个只读角色,授给用户而非直接授权限,后续调整只需动角色定义
账户锁定、权限回收、外部凭证清理三者缺一不可。生产环境里,最容易被忽略的是角色继承权限和配置文件硬编码——它们会让前面所有 SQL 操作形同虚设。


















