滚动新闻 →
密西西比州参议员科洛姆获川普公开肯定 民主党中期选举成果显现 SpaceX星舰第15次试飞突破轨道技术 机械哥斯拉首次亮相 唐元隽因涉嫌为中共搜集美国异议人士信息被纽约法院判缓刑三年 欧洲参与俄乌和谈遭分歧 战俘交换后冲突再升级 美国财长:伊朗黑客利用中国AI攻击法国超市冷藏系统 唐元隽涉非法搜集海外异议人士信息被判缓刑 双黄丑闻蔓延白宫 卢特尼克或因放水被问责 黄仁勋辞任事件引安全担忧 中共渗透手段升级 加拿大政界呼吁彻查中共海外警务据点 清华特等奖学金评选引争议 AI方向占比近全 前CIA局长之子因传播儿童色情制品被起诉 突发:新奥尔良港油轮撞上客船 多人落水 美国联邦航空总署实施全国航班停飞措施 退伍军人事务部长披露福利审批通过率高达94% 黄仁勋被美众议院三大委员会要求出席闭门听证会 法国10月通胀率突破3.7% 创近3年新高 山西男子砍伤妻岳母未被批捕 释放后勒死妻子引争议 黄仁勋辞职引台湾日本政界高度关注 唐元隽因向中共提供情报获三年缓刑 欧几里得望远镜发布首批观测数据 助力探索暗宇宙之谜 内蒙古化工厂氨气泄漏事件引争议,官方称属无毒催泪弹演练 英伟达共谍风暴升级 高阶芯片流向成焦点 西安村民因欠款问题冲击政务中心 无锡超算中心遭黑客入侵数据遭出售 网民质疑掩盖真相 Anthropic IPO超额认购六倍 加拿大各界在老兵纪念日缅怀阵亡将士并致敬军人 习近平称继承孙中山理念 学者质疑历史背离 孙中山纪念大会异常引关注 习健康状况引猜测 中国AI模型被指用于伊朗网络攻击 法国超市遭大规模破坏 雕刻大师现场展示技艺 纽约跨年水晶球亮相时代广场 Google Distributed Cloud 是什么,无法全部迁移到公有云的企业可以怎样部署 新疆库车市发生5.0级地震 乌鲁木齐民众普遍感知明显 美以海军高层会谈 土耳其卡塔尔签署防御协议 涉嫌为中共搜集情报 唐元隽纽约获三年缓刑 上海交大基因编辑实验致女童死亡 处罚仅限开除引争议 民主党参议院领袖选举引争议 范霍伦挑战舒默权威 江苏句容城管强抢餐车引摊贩冲突 中共借孙中山纪念进行统战操作 学者质疑继承论述模糊 黄乐与华为关联引调查 深圳数据中心牵出供应链疑云 京沪高铁山东段故障引争议 施工挖断电缆遭质疑

MySQL GRANT 怎么使用?给 PHP 网站创建合适的数据库访问权限

发布时间: 2026-10-24 18:00:03    最后更新: 2026-11-12 19:46:01    阅读:83  约11 分钟阅读     

MySQL GRANT 怎么使用?给 PHP 网站创建合适的数据库访问权限
图片说明:示意图   图片来源:Public Domain(公有领域)
PHP网站连接MySQL时,最容易被忽略的安全问题之一,就是数据库账号到底拥有多大的权限。很多网站为了省事直接使用root,或者给应用账号授予ALL PRIVILEGES。这样做在开发环境可能感觉方便,但一旦网站程序、插件或者接口出现SQL注入或其他漏洞,攻击者拿到的就不只是某张表的权限,而可能进一步获得整个数据库甚至更多服务器级能力。

MySQL的GRANT机制真正解决的问题,就是把“网站需要做什么”和“数据库允许做什么”分开。对于PHP应用来说,通常应该建立独立的应用账号,只授予程序运行过程中真正需要的权限。

最常见的权限包括SELECT、INSERT、UPDATE和DELETE。SELECT用于读取数据,INSERT用于新增记录,UPDATE用于修改记录,DELETE用于删除记录。CREATE、ALTER、DROP等DDL权限则涉及数据库结构变化,生产环境中的普通PHP运行账号通常没有必要拥有这些权限。

例如一个网站运行时只需要读取、增加和修改业务数据,可以建立这样的账号:

CREATE USER 'php_user'@'localhost'
IDENTIFIED BY '使用密码管理器生成的强密码';

GRANT SELECT, INSERT, UPDATE
ON dbname.*
TO 'php_user'@'localhost';

这里的localhost非常重要。它表示这个账号只允许从本机连接。如果PHP和MySQL运行在同一台服务器上,通常没有必要为了方便而写成'%'。'%'代表更宽泛的主机匹配范围,会扩大数据库账号可以尝试连接的位置。

如果网站还需要删除业务记录,可以增加DELETE:

GRANT SELECT, INSERT, UPDATE, DELETE
ON dbname.*
TO 'php_user'@'localhost';

而CREATE、ALTER、DROP等权限最好与网站运行账号分开。比如数据库迁移、表结构升级由部署账号或者维护人员执行,而PHP运行账号只负责正常业务操作。这样即使网站程序被攻破,攻击者能够利用的数据库权限也会受到限制。

GRANT也可以精确到单张表。例如网站的统计账号只需要读取orders表:

GRANT SELECT
ON dbname.orders
TO 'report_user'@'localhost';

如果不同账号负责不同功能,还可以进一步限制权限。例如后台程序可以修改内容表,而报表账号只能读取数据。权限越接近实际业务需求,发生应用漏洞以后造成的影响范围通常越容易控制。

MySQL还支持列级权限。例如某个账号只需要读取用户姓名和注册时间:

GRANT SELECT (username, created_at)
ON dbname.users
TO 'report_user'@'localhost';

不过列级权限会增加权限管理复杂度。对于大多数普通PHP网站来说,先做好数据库、表和账号之间的隔离,往往比把每一个字段都拆成权限更加实际。

另一个容易流传的错误,是认为执行GRANT以后必须手动执行FLUSH PRIVILEGES。对于正常使用CREATE USER、GRANT、REVOKE等SQL语句修改权限的情况,并不需要额外执行这个命令。MySQL会立即处理这些权限变化。FLUSH PRIVILEGES主要用于权限表被直接修改等特殊场景,因此不应该作为每一次GRANT后的固定步骤。

查看权限时,也不要直接查询mysql.user然后寻找一个所谓的privileges字段。更可靠的方法是:

SHOW GRANTS FOR 'php_user'@'localhost';

这个命令能够直接显示该账号实际获得的授权。例如:

GRANT SELECT, INSERT, UPDATE
ON `dbname`.* TO `php_user`@`localhost`

如果需要检查当前用户,可以使用:

SELECT CURRENT_USER();

对于生产环境的权限审计,还应该把数据库授权和应用账号、服务器账号分别考虑。数据库用户并不等于Linux用户,PHP-FPM运行账户也不等于MySQL账户。每一层都应该只拥有完成自身工作的权限。

密码方面,也不要把“12位、大小写、数字、特殊字符、每三个月更换一次”当成MySQL统一规定。实际要求取决于MySQL服务器配置以及组织自己的安全政策。更重要的是不要在源代码、Git仓库或者公开配置文件中硬编码生产数据库密码。

PHP代码可以通过环境变量或受保护的配置文件取得数据库凭据。例如使用PDO:

$host = 'localhost';
$dbname = 'dbname';
$user = 'php_user';
$pass = getenv('DB_PASSWORD');

$pdo = new PDO(
"mysql:host=$host;dbname=$dbname;charset=utf8mb4",
$user,
$pass,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false
]
);

这里还需要区分“数据库权限”和“SQL注入防护”。即使PHP账号只有SELECT、INSERT、UPDATE权限,程序仍然可能因为SQL注入产生严重问题。因此数据库权限只是最后一道限制,SQL参数绑定、输入验证和正确的授权检查仍然必须存在。

如果PHP和MySQL不在同一台服务器上,还需要处理网络访问问题。这时不能简单地把账号改成'php_user'@'%'然后打开3306端口。更合理的做法是限制允许连接数据库的服务器地址,并结合防火墙、安全组以及MySQL账户的host限制控制访问来源。如果环境支持TLS,还应该配置MySQL客户端与服务器之间的加密连接,并验证服务器证书,而不是仅仅打开一个所谓的SSL选项。

MySQL 8.x还支持角色。角色适合多个账号共享一套权限。例如可以创建一个只读角色:

CREATE ROLE 'app_reader';

GRANT SELECT
ON dbname.*
TO 'app_reader';

CREATE USER 'php_report'@'localhost'
IDENTIFIED BY '使用密码管理器生成的强密码';

GRANT 'app_reader'
TO 'php_report'@'localhost';

这样以后需要调整报表账号权限时,可以修改角色,而不必逐个修改大量用户。对于大型SaaS或者多应用环境,这种管理方式会更加清晰。

如果网站同时存在开发、测试和生产环境,也最好不要让三个环境共享同一个数据库账号。开发环境账号、测试环境账号和生产环境账号应该分别管理。更进一步,还可以让迁移工具使用拥有DDL权限的独立账号,而PHP-FPM使用没有CREATE、ALTER、DROP权限的运行账号。

生产环境还需要考虑数据库连接数量。max_connections = 100并不是一个通用的最佳值。PHP-FPM可能同时运行多个worker,如果每个worker都能够建立数据库连接,PHP并发量与MySQL连接数之间就会形成直接关系。数据库服务器的内存、查询持续时间、连接建立方式以及应用架构都需要一起计算。简单把max_connections设置成一个漂亮的整数,反而可能让数据库在高峰期耗尽内存。

PHP中的PDO也不能简单等同于传统数据库连接池。PHP-FPM环境通常需要根据实际部署方式考虑普通连接、持久连接、外部连接池或者数据库代理。真正重要的是控制连接数量、及时释放连接以及缩短长时间运行的SQL,而不是为了“使用连接池”三个字而增加复杂组件。

对于权限较大的账号,还应该定期执行:

SHOW GRANTS FOR 'php_user'@'localhost';

检查账号是否出现不必要的权限。特别是网站经过多年升级以后,数据库账号经常会积累历史权限。一个最初只需要SELECT和INSERT的账号,几年以后可能已经被开发人员临时增加了UPDATE、DELETE、CREATE甚至更高权限,却从来没有回收。

数据库权限设计还有一个非常重要的原则:不要把权限控制当成业务授权。比如PHP账号拥有UPDATE权限,并不意味着当前登录用户就应该能够修改所有用户的数据。数据库权限解决的是“应用程序能不能执行UPDATE”,而PHP业务逻辑解决的是“这个用户有没有权修改这一条记录”。SaaS系统中的tenant_id隔离、管理员权限和普通用户权限仍然必须在应用层严格检查。

因此,一个比较稳妥的PHP网站数据库权限结构通常是:生产环境使用独立MySQL账号,不使用root运行网站;账号限制连接来源;PHP运行账号只拥有业务所需的SELECT、INSERT、UPDATE、DELETE等权限;DDL操作使用独立维护账号;不同应用和环境使用不同账号;数据库连接使用安全的凭据管理方式;跨服务器连接时限制网络来源并根据需要启用TLS;定期使用SHOW GRANTS审查授权。

GRANT真正有价值的地方,并不是让数据库管理员记住一长串SQL语法,而是建立一道清晰的权限边界。网站程序应该能够完成自己的工作,却不应该因为程序出现漏洞,就自动拥有修改数据库结构、访问其他应用数据或者执行不必要操作的能力。对于PHP网站来说,最小权限不是一项额外功能,而应该从数据库账号创建的第一天就成为架构的一部分。
本文作者
程越(Kevin Cheng)
IT与人工智能技术资深编辑

喜欢这篇报道?

使用下面的功能,方便以后继续阅读和分享 MNewsTV

设为 Google 新闻首选来源 让 Google 新闻优先显示 MNewsTV 的最新报道 ›
★ 我的收藏 查看已经收藏的文章
关于文章收藏 收藏不需要注册帐号,收藏信息仅保存在当前浏览器中。 删除收藏请进入「我的收藏」进行管理。
分享这篇报道

捐助(Paypal): https://www.paypal.me/observeccp
订阅中国观察电报 Telegram : https://t.me/s/ObserveCCP