滚动新闻 →
美国强化福利欺诈打击行动 逾40人涉案;中共五中全会前夕人事风向引关注 Windows 11 用户账户密码怎么修改?忘记密码之前应该掌握这些方法 MySQL GRANT 怎么使用?给 PHP 网站创建合适的数据库访问权限 加州两万名非公民身份核查引争议 涉选举犯罪 日本防卫专家列三红线应对中共区域安全挑战 古代诗词中的春天为什么如此丰富 美国情报机构披露伊朗暗杀阴谋 川普警告或重启军事行动 168断食法并非万能!营养师详解适用人群与饮食禁忌 纽约提前投票首日选民热议民生议题 期待选举带来实质影响 日本冲绳遭遇超级台风蔷琵袭击 超12.8万户断电 21大前人事大洗牌 中共高层内斗白热化 法国部署7万警力应对蒙面示威者冲突 莲藕与中国传统饮食文化 张婉莹涉台籍官员家属监控案不认罪 将于11月30日受审 哥大中国项目主任孙哲被指曾执教中共军校 毛笔为什么需要经常保养 培养孩子欣赏别人优点的能力 为什么视频拍摄前应该检查存储空间 海南航空航班疑似误入跑道遭空管拦截 机组人员质疑操作规范 朱元璋为什么能够从贫苦农民成为皇帝 问界智能座椅行驶中异常移动引车主恐慌 改善居住环境时为什么不应该只追求外观 胡塞武装袭击亚丁机场,红海局势持续升级 美军中东基地人员撤离 航母备战应对伊朗威胁 米粉文化为什么在中国南方如此丰富 江西警方跨省抓捕环保志愿者 张文斌疑因曝光污染遭拘 住进森林深处,加拿大芬迪国家公园把秋天藏在树影之间 网约车司机遗弃病重男子致其死亡,家属索赔96万元 汽车故障码到底应该怎么看 川普称美军返航途中将处理古巴问题 卢比奥呼吁内部变革 金正恩突访丹东之际 网络频传其猝逝传闻 美国五角大厦公开第七批UFO档案 神秘黑三角引发热议 美战争部:孔子学院改名后仍渗透校园,80个组织被清除 汽车雷达到底是怎么工作的 台风蔷琵袭击台湾后直扑日本 冲绳40航班取消 川普威胁动武:伊朗若拒协议或面临新一轮打击 北美房屋保温性能为什么会影响长期居住成本 为什么投资之前应该先考虑现金储备 游艇内饰如何影响二手市场价值 经纪人如何防止演员被制片公司低估

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

发布时间: 2026-10-24 18:00:03    最后更新: 2026-10-24 19:26:54    阅读:12  约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网站来说,最小权限不是一项额外功能,而应该从数据库账号创建的第一天就成为架构的一部分。

喜欢这篇报道?

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

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

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