MySQL不提供禁止用户改自己密码的权限粒度,唯一有效控制方式是启用validate_password插件校验强度、用ACCOUNT LOCK禁用账户、回收CREATE USER及mysql.*写权限。

MySQL 本身不提供「禁止某用户修改自己密码」的权限粒度控制。你无法通过 GRANT/REVOKE 关闭某个用户的 ALTER USER 或 SET PASSWORD 权限——只要该用户有 CREATE USER、UPDATE(对 mysql.user 表)或更高权限,就能改自己密码。
真正能“拦住”密码修改的,只有两个实际路径:插件策略拦截(校验失败)、或彻底剥夺写 mysql.user 的能力。直接操作 mysql.user 表不仅危险,而且在 MySQL 8.0+ 中几乎无效——因为密码不再存于 Password 字段,而是在 authentication_string,且受插件强约束。
validate_password 插件才是实际生效的“限制器”
所谓“禁止改密码”,其实是让 ALTER USER ... IDENTIFIED BY 或 SET PASSWORD 命令执行时直接报错:ERROR 1819 (HY000): Your password does not satisfy the current policy requirements。这个错误来自 validate_password 插件,不是权限系统。
- 它只在校验阶段介入:创建用户、
ALTER USER、SET PASSWORD时触发,不追溯已有弱密码 - 策略等级(
validate_password_policy)设为MEDIUM或STRONG时,6位纯数字密码(如'123456')必然失败 - 即使你用
UPDATE mysql.user SET authentication_string = 'xxx' WHERE User='u1'直写哈希值,只要插件已启用,这条UPDATE也会被拒绝(报同样 1819 错误) - 想绕过?必须先
UNINSTALL PLUGIN validate_password,否则任何写入mysql.user密码字段的操作都会被拦截
为什么直接 UPDATE mysql.user 在 MySQL 8.0+ 中不可靠
MySQL 5.7 及更早版本中,Password 字段可存哈希值,PASSWORD() 函数可用;但 8.0+ 已移除 Password 字段,统一用 authentication_string,且 PASSWORD() 函数被废弃(调用会报错 ERROR 1548 (HY000): Plugin 'validate_password' is disabled 或直接拒绝)。
-
UPDATE mysql.user SET authentication_string = SHA2('mypass',256) WHERE User='u1'—— 不生效,MySQL 不识别裸 SHA2 值,必须用VALIDATE_PASSWORD_STRENGTH()兼容格式 - 即使手算出正确哈希(如
*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9),写入后也需FLUSH PRIVILEGES,但该命令在 8.0+ 中对密码字段已无效果 - 最麻烦的是:写完表后,用户下次连接可能因认证插件不匹配直接失败,错误信息常为
ERROR 1045 (28000): Access denied for user
真正可控的替代方案:ACCOUNT LOCK + 权限剥离
如果你的目标是“让用户无法再登录并改密”,而不是“允许登录但禁改密码”,那么以下组合是稳定、安全、8.0+ 原生支持的做法:
- 用
ALTER USER 'u1'@'%' ACCOUNT LOCK立即禁用账户,用户连接时直接报ERROR 3118 (HY000): Access denied for user 'u1'@'x.x.x.x'. Account is locked. - 回收其
CREATE USER、INSERT、UPDATE权限(特别是对mysql.*):REVOKE CREATE USER ON *.* FROM 'u1'@'%'; REVOKE INSERT, UPDATE ON mysql.* FROM 'u1'@'%'; - 确认其无
SYSTEM_USER或APPLICATION_PASSWORD_ADMIN等高危权限(这些权限可绕过常规限制) - 注意:
USAGE权限无法回收,所以不能靠它“禁用”;DROP USER是彻底删除,但会丢失授权历史,慎用
插件未启用时,用户仍可能改密的关键盲点
很多线上环境禁用了 validate_password(SELECT PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME='validate_password' 返回 DISABLED),此时所有密码修改均无强度校验——哪怕设成 'a' 都成功。这种情况下,“限制改密”完全失效,唯一防线只剩权限控制。
- 检查是否启用:
SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'validate_password'; - 若为
DISABLED,临时启用:INSTALL PLUGIN validate_password SONAME 'validate_password.so'; - 但要注意:某些云厂商 RDS(如阿里云、腾讯云)默认禁用该插件且不允许手动安装,此时只能依赖权限回收 + ACCOUNT LOCK
- 永远别假设“没装插件=安全”,它只是把校验关掉了,反而让弱密码泛滥更隐蔽
实际生产中,没人靠 UPDATE mysql.user 实现密码管控。有效动作只有三个:开插件卡强度、锁账户断连接、收权限防越权。其余都是徒增故障点。


















