MySQL权限模型是访问控制第一道闸门,粒度细至列行级,需慎用通配符授权、显式指定认证插件、禁用匿名用户、区分REVOKE与DROP USER、结合VIEW+DEFINER实现脱敏,并配合TLS、审计日志等构建纵深防御。

MySQL 权限模型直接决定数据能否被非法读写
MySQL 的权限不是附加功能,而是访问控制的第一道闸门。没有显式授权的用户,默认无法执行任何数据操作——哪怕只是 SELECT。权限粒度细到库、表、列甚至行(通过视图或条件限制),意味着“能连上”不等于“能查到”,更不等于“能删掉”。常见误操作如给 root@'%' 开放远程访问却不设强密码,或用 GRANT ALL ON *.* 创建应用账号,实际已绕过大部分安全约束。
CREATE USER 和 GRANT 语句必须配合 IDENTIFIED WITH 显式指定认证插件
MySQL 8.0+ 默认使用 caching_sha2_password 插件,但旧客户端可能不兼容;若降级为 mysql_native_password 又可能削弱传输层保护。权限分配时容易忽略这点,导致应用连不上或凭据明文传输。
- 新建用户务必指定插件:
CREATE USER 'appuser'@'192.168.1.%' IDENTIFIED WITH caching_sha2_password BY 'StrongPass!2024'; - 授予权限时避免通配符滥用:
GRANT SELECT, INSERT ON mydb.orders TO 'appuser'@'192.168.1.%';,而非GRANT ALL ON *.* - 禁用匿名用户和空密码:
DROP USER ''@'localhost';,并检查mysql.user表中authentication_string是否为空
REVOKE 和 DROP USER 的行为差异影响权限回收实效性
REVOKE 只撤销权限,不删除账号;DROP USER 才真正移除身份。但很多人只 REVOKE 却没 FLUSH PRIVILEGES,结果权限缓存未更新,旧权限仍生效。更隐蔽的问题是:MySQL 不自动清理已失效账号的连接,残留会话可能继续持有旧权限上下文。
- 撤销后必须执行:
FLUSH PRIVILEGES;(仅在直接修改mysql.user表后才强制需要;用GRANT/REVOKE通常自动刷新) - 确认权限已清空:
SHOW GRANTS FOR 'olduser'@'host'; - 强制终止残留会话:
KILL CONNECTION [id];,ID 来自SHOW PROCESSLIST;
数据脱敏与权限隔离需靠 VIEW + DEFINER 而非单纯 GRANT
仅靠表级 GRANT 无法实现字段级遮蔽(如隐藏身份证号中间四位)。这时必须用 CREATE VIEW 定义受限结果集,并用 SQL SECURITY DEFINER 绑定高权限所有者,让低权限用户透过视图间接访问——视图逻辑由定义者权限执行,但调用者只能看到视图暴露的列。
CREATE DEFINER = 'admin'@'localhost' SQL SECURITY DEFINER VIEW safe_users AS SELECT id, username, CONCAT(LEFT(id_card, 3), '****', RIGHT(id_card, 4)) AS masked_id_card FROM users;
然后只对普通用户授予 SELECT ON safe_users。这种方式绕过了列权限(GRANT SELECT(col1,col2) ON...)在多数 MySQL 版本中不支持动态脱敏的限制。
audit_log 插件)、定期权限审查组合使用。最容易被忽略的是:权限变更后未验证实际效果,以及把账号密码硬编码在应用配置里——这会让所有精细的权限设计形同虚设。










