导读:本期聚焦于鱼儿创作的《数据库权限管理如何安全使用GRANT与REVOKE语句?》,敬请观看详情。把ALL PRIVILEGES直接授予业务账号,等于把数据库钥匙交给每一个能连上服务的人。GRANT与REVOKE不是简单的授权与回收,它们涉及权限粒度、主机限制、对象范围、角色继承以及授权传递等多个维度,任何一处配置过大都会让攻击者或误操作获得超出预期的能力。本文从最小权限原则出发,结合MySQL语法展示如何创建只读账号、业务读写账号和备份账号,并说明如何通过精确到库、表、列以及限制来源IP来收缩风险面。文章还会分析REVOKE执行后权限仍然生效的几个原因,包括授权层级不匹配、全局权限残留和角色继承等,并演示如何用SHOW GRANTS验证回收结果。同时会讨论WITH GRANT OPTION的传递风险和主机名通配符的常见误区,帮助建立一套可落地的数据库权限配置基线,避免把ALL PRIVILEGES当作默认选项。

数据库账号权限很少被当成独立的安全边界来看待。很多团队在搭建环境时,为了快速跑通业务,常常直接把所有权限授予应用账号,例如执行一条类似GRANT ALL PRIVILEGES ON *.*的语句。短时间内确实省事,但等系统稳定后,这些账号仍然持有删除库表、读写其他业务库甚至管理用户的能力。一旦应用出现SQL注入、配置泄露或内部误操作,影响范围会被无限放大。GRANT和REVOKE语句的真正价值不在于能否授权和回收,而在于它们能否把权限压缩到刚好满足业务运行的程度,并为后续审计提供清晰依据。

本文围绕数据库权限配置中的常见场景,结合MySQL语法,说明如何通过精确的对象范围、主机限制和权限类型来收紧访问控制。随后会分析REVOKE在实际执行中容易失效的原因,并给出一个可落地的业务账号与运维账号分离配置示例。

数据库权限管理如何安全使用GRANT与REVOKE语句?

GRANT语句的对象范围与主机限制

GRANT语句的授权范围由ON后面的对象层级决定。最宽泛的是*.*,它代表所有数据库的所有表;其次是db_name.*,只覆盖某个库的全部表;更细的是db_name.table_name,只针对单表;最细的可以到列级别,例如SELECT (order_id, customer_name),表示只能读取指定列。很多安全策略失败的根源,就是对象范围选得过大。一个只负责统计订单编号和客户名的报表任务,如果被授予app_db.*的SELECT权限,就能读取用户手机号、地址等敏感字段;如果只授予两个列的SELECT权限,即便这个账号被拖库,暴露的数据也会小得多。

主机限制同样不可忽视。MySQL中的账号由用户名和来源主机共同组成,'report_user'@'10.0.2.15'与'report_user'@'%'是两个不同账号。来源主机写%表示允许任意主机连接,这在生产环境几乎不应该出现。更合理的做法是,如果应用部署在固定网段,就写10.0.2.%;如果只有本机备份任务,就写127.0.0.1或localhost。主机部分支持百分号和下划线通配符,但要注意%可以匹配空串,因此'user'@'192.168.%'不仅覆盖C段,还可能匹配以192.168开头的其他主机形式,具体应结合MySQL文档与网络规划确认。

下面是一个创建只读账号的示例,它把权限压缩到指定库,并将来源限制在应用所在网段:

CREATE USER 'readonly_app'@'192.168.10.%' IDENTIFIED BY 'ChangeMe_Str0ng';
GRANT SELECT ON app_db.* TO 'readonly_app'@'192.168.10.%';
FLUSH PRIVILEGES;

这个账号只能对app_db库执行SELECT,不能写入、不能建表,也无法访问mysql系统库。对于报表服务、数据导出任务这类只读场景已经足够。实际配置时还应替换默认密码,避免使用常见弱口令。

GRANT OPTION与通配符带来的权限扩散风险

GRANT语句末尾可以附带WITH GRANT OPTION,表示被授权者能把当前权限再授予其他用户。这个选项非常危险,因为它会让权限管理出现多级扩散。例如一个开发主管被授予了app_db.*上的SELECT、INSERT、UPDATE权限,并附带GRANT OPTION,那么他就可以创建新用户,再把写权限转授给其他成员。安全管理员可能完全不知道这些子账号的存在,后续回收权限时会发现授权关系已经变得复杂,甚至出现某个人同时通过多个路径拥有同一权限的情况。

除非团队有自动化审批和授权平台,否则普通业务账号、开发测试账号都不应该带有GRANT OPTION。需要临时授权时,应由数据库管理员统一创建账号并控制范围。这样可以保持授权路径单一,回收和审计都能做到闭环。

与授权扩散类似的还有通配符误用。除了主机部分,MySQL在授权表中存储的对象名一般不是LIKE模式,通常数据库名、表名中的下划线不会被当作通配符处理,但不同版本和不同权限级别的行为可能存在差异。真正容易出问题的是主机名中的%。例如有人认为'ops_user'@'10.%'只匹配内网10网段,实际上它可能匹配10开头的任意字符串,具体匹配规则需要结合主机解析。因此更稳妥的写法是明确到子网段,例如'ops_user'@'10.0.10.%',而不是用宽泛的10.%或%。

下面演示一个运维账号的最小授权。它只被允许在指定库执行查询和备份相关操作,并且来源IP被严格限制:

CREATE USER 'ops_backup'@'10.0.10.8' IDENTIFIED BY 'B@ckup_P@ss';
GRANT SELECT, SHOW VIEW, TRIGGER, LOCK TABLES ON app_db.* TO 'ops_backup'@'10.0.10.8';

这里没有使用ALL PRIVILEGES,也没有开放任意主机。备份任务如果需要读取库表结构和触发器,就必须给SHOW VIEW和TRIGGER;如果使用mysqldump且涉及锁表,还需要LOCK TABLES。这些权限应当按需授予,而不是简单塞一个ALL。

REVOKE回收权限的细节与失效场景

REVOKE语句的基本格式是REVOKE privilege_list ON object FROM user。它和GRANT一样,回收时也必须指定一致的权限范围和对象层级。比如之前执行的是GRANT SELECT ON app_db.* TO 'readonly_app'@'192.168.10.%',如果回收时使用REVOKE SELECT ON *.* FROM 'readonly_app'@'192.168.10.%',MySQL不会因为*.*包含了app_db.*就自动移除那个权限,因为授权表里记录的是不同层级的独立条目。正确的做法是保持相同的app_db.*范围。

另一个常见误解是认为REVOKE可以删除用户或禁止登录。实际上REVOKE只会移除特定权限,用户本身仍然存在,并且可能还持有其他权限。如果只回收了库级SELECT,但用户还有全局USAGE权限或其他库的权限,应用连接后仍能登录,只是在原库执行SELECT时被拒绝。要彻底禁止登录,可以使用ALTER USER 'username'@'host' ACCOUNT LOCK,或者直接DROP USER 'username'@'host'。

执行完REVOKE后,必须通过SHOW GRANTS验证结果。例如:

REVOKE SELECT ON app_db.* FROM 'readonly_app'@'192.168.10.%';
SHOW GRANTS FOR 'readonly_app'@'192.168.10.%';

有时权限没有被回收,是因为账号在多个授权层级上都存在记录。例如全局有SELECT,库级也有SELECT,只回收库级后全局SELECT仍然生效。类似地,如果用户通过角色继承权限,单独REVOKE用户自身权限可能不影响通过角色获得的权限。因此排查权限残留时,要同时检查全局、库、表和列级授权,以及角色关系。

也可以在回收前先查看当前权限,确认是否存在多余的GRANT OPTION:

SHOW GRANTS FOR 'app_writer'@'10.0.1.%';

业务账号、只读账号与管理账号分离配置

一个较安全的数据库账号体系至少包含三类:业务读写账号、只读账号和备份或运维账号。它们之间不能混用。业务读写账号只授予应用所需库的INSERT、UPDATE、DELETE、SELECT,且通常不授予DDL权限;只读账号只授予SELECT;备份账号按备份工具需要授予SELECT、SHOW VIEW、TRIGGER、LOCK TABLES;管理账号则由DBA单独持有,不配置到业务服务器。

下面给出一个基于MySQL的完整示例,假设业务库名为app_db,应用网段为10.0.1.%,报表服务网段为10.0.2.%,备份主机为10.0.10.8:

-- 业务读写账号
CREATE USER 'app_writer'@'10.0.1.%' IDENTIFIED BY 'Wr!te_P@ss_App';
GRANT SELECT, INSERT, UPDATE, DELETE ON app_db.* TO 'app_writer'@'10.0.1.%';

-- 报表只读账号
CREATE USER 'report_reader'@'10.0.2.%' IDENTIFIED BY 'Re@d_Only_App';
GRANT SELECT ON app_db.* TO 'report_reader'@'10.0.2.%';

-- 备份账号
CREATE USER 'backup_user'@'10.0.10.8' IDENTIFIED BY 'B@ckup_User_P@ss';
GRANT SELECT, SHOW VIEW, TRIGGER, LOCK TABLES ON app_db.* TO 'backup_user'@'10.0.10.8';

这些账号都遵循了最小权限原则:不做跨库授权,不开放任意主机,不授予DDL或管理权限。应用上线后如果需要对表结构变更,应由DBA使用单独的管理账号执行,而不是把ALTER权限交给应用。这样可以避免应用逻辑漏洞被用来直接删除表或修改字段。

日常审计可以定期检查用户列表和权限分布。以下查询可以快速查看当前存在的用户,过滤掉系统内置账号:

SELECT user, host
FROM mysql.user
WHERE user != 'mysql.sys'
  AND user != 'mysql.session'
  AND user != 'mysql.infoschema';

根据查询结果,再对异常账号使用SHOW GRANTS做进一步排查。安全配置不是一次到位的工作,新上线的服务、人员变动、临时活动都可能引入新的授权,只有把GRANT与REVOKE的粒度、范围、验证流程固定下来,才能持续降低权限失控风险。

GRANT语句REVOKE语句数据库权限管理修改时间:2026-09-23 23:36:32

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0923/61087.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。