如何禁止无GRANT OPTION的MySQL用户修改其他用户密码?
嘿,这个问题的根源其实藏在MySQL的权限逻辑里:虽然user1没有GRANT OPTION,但你给的ALL PRIVILEGES默认包含了全局UPDATE权限,这就允许user1直接修改mysql.user这个系统表(存储所有用户账号和权限的核心表),或者用ALTER USER语句篡改其他用户的密码。
要搞定这个问题,我们需要精准收回user1的相关权限,同时尽量不影响他的正常业务操作,具体步骤如下:
1. 先确认user1的权限详情
首先得搞清楚user1到底有哪些权限,用root或其他有管理权限的账号执行:
SHOW GRANTS FOR 'user1'@'your_host';
记得把your_host换成实际的主机标识,比如%(所有主机)或者localhost(本地)。
2. 选择合适的权限收回方式
根据你的业务需求,选下面一种方式就行:
方式一:精准收回系统表的修改权限
如果user1需要保留其他全局权限(比如PROCESS、RELOAD这类),只收回他对mysql.user表的UPDATE权限:
REVOKE UPDATE ON mysql.user FROM 'user1'@'your_host';
这样user1就没法直接修改用户表的内容了,自然改不了user2的密码。
方式二:收回用户管理类权限
如果user1根本不需要创建或修改其他用户的能力,直接收回CREATE USER和ALTER USER这两个权限——这俩权限是执行ALTER USER改密码的关键:
REVOKE CREATE USER, ALTER USER ON *.* FROM 'user1'@'your_host';
方式三:重新授予最小权限(最推荐)
其实最稳妥的做法是遵循最小权限原则:先收回user1的全部权限,再只给他业务数据库所需的权限,彻底避免全局权限带来的风险:
-- 先清空所有权限 REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'user1'@'your_host'; -- 只授予业务数据库的全部权限(替换成你的实际业务库名) GRANT ALL PRIVILEGES ON your_business_db.* TO 'user1'@'your_host'; -- 如果需要全局的特定权限(比如查看进程),单独加,别用ALL -- GRANT PROCESS ON *.* TO 'user1'@'your_host';
3. 验证是否生效
切换到user1的账号,尝试修改user2的密码:
ALTER USER 'user2'@'your_host' IDENTIFIED BY 'test_pass';
或者直接改系统表:
UPDATE mysql.user SET authentication_string=PASSWORD('test_pass') WHERE User='user2' AND Host='your_host';
如果操作失败,提示ERROR 1044 (42000): Access denied for user 'user1'@'your_host' to database 'mysql'或者类似的权限不足错误,就说明配置生效了。
小提醒
- 执行
GRANT/REVOKE后不用手动FLUSH PRIVILEGES,MySQL会自动刷新权限(除非你直接修改了mysql.user表才需要)。 - 一定要用有
GRANT OPTION的账号(比如root)来执行这些权限修改操作。
内容的提问来源于stack exchange,提问作者APH

