怎么用mysql实现用户权限控制_mysql项目安全设计

来源:这里教程网 时间:2026-02-28 20:39:38 作者:

MySQL 用户权限控制的核心是 GRANT 和 REVOKE

MySQL 的权限模型基于「用户账号 + 主机范围 + 权限级别 + 权限类型」四维组合,不是靠应用层硬编码角色判断。直接操作

mysql.user
表极危险,必须用
GRANT
语句授予权限,否则权限不会生效,甚至可能破坏系统表结构。

GRANT SELECT, INSERT ON mydb.orders TO 'app_user'@'10.20.30.%'
—— 只给特定 IP 段的用户最小必要权限
权限只对显式指定的数据库/表生效,
GRANT ... ON *.*
是高危操作,生产环境禁止使用
执行
GRANT
后必须跟
FLUSH PRIVILEGES
(仅在直接改系统表后需要),正常用
GRANT
不需要手动刷新
用户主机部分写
'%'
允许任意来源连接,但若 MySQL 部署在内网,应严格限制为
'192.168.1.%'
或具体容器 IP

避免用 root 或同级账号跑应用服务

项目上线前必须创建专用账号,root 权限一旦泄露等于整库沦陷。常见错误是开发时用 root 测试,上线忘记切换,或把账号密码写死在 config.php / application.yml 里。

建账号用
CREATE USER 'webapp'@'172.18.0.5' IDENTIFIED BY 'strong_pass_2024!'
,密码必须含大小写字母、数字、符号
应用配置中禁止出现
user=root
,检查所有
.env
config/database.php
、Docker Compose
environment:
字段
如需跨库关联查询,不要给
ALL PRIVILEGES ON *.*
,而是明确授权:
GRANT SELECT ON db_a.users TO 'webapp'@'...'; GRANT SELECT, INSERT ON db_b.logs TO 'webapp'@'...'

权限粒度要落到表甚至列级别

不是所有业务都需要读全表。比如用户中心模块只需查

users(id, name, avatar)
,但不应能读
users.password_hash
users.phone
(除非实名认证流程)。

列级授权示例:
GRANT SELECT(id, name, email) ON myapp.users TO 'report_user'@'%'
敏感字段如
password_hash
id_card
bank_account
应单独建加密表,用独立账号访问,且该账号无
INDEX
ALTER
权限
写权限比读更敏感:一个订单服务账号,应只有
INSERT ON orders
UPDATE ON orders WHERE status='pending'
(后者需应用层逻辑控制,MySQL 本身不支持行级条件授权)

定期审计权限与失效账号

权限不是设一次就完事。人员变动、服务下线、临时调试账号都可能遗留高危凭证。

查所有非系统账号:
SELECT User, Host, authentication_string FROM mysql.user WHERE User NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root');
查某账号具体权限:
SHOW GRANTS FOR 'api_user'@'10.1.2.%'
禁用不用的账号不是删库,而是用
DROP USER 'legacy_app'@'%'
;若只是临时停用,可用
RENAME USER 'old'@'%' TO 'old_disabled'@'%'
避免配置残留
MySQL 8.0+ 支持密码过期策略:
ALTER USER 'webapp'@'%' PASSWORD EXPIRE INTERVAL 90 DAY
权限设计最易被忽略的点是「连接来源不可信时,即使权限再小也危险」——比如允许
'app'@'%'
连接,攻击者只要拿下任意一台能连 MySQL 的服务器,就能绕过网络隔离。真正安全的起点,是把
Host
锁死到最小 IP 范围,并配合防火墙双重过滤。

相关推荐