最小权限原则不能阻止SQL注入发生,但能限制攻击者利用注入账号所能获取的数据范围和操作能力;它通过列级授权、视图封装、禁用高危权限及修复配置漏洞来降低危害。

数据库用户权限不能阻止 SQL 注入发生,但能显著限制其实际破坏范围——关键不是“防注入”,而是“断后路”。
只给 SELECT 权限的用户为何仍可能被拖库?
很多团队误以为只要不给 INSERT/UPDATE/DELETE 就安全了,但实际中:
• 攻击者可用 UNION SELECT 把敏感表(如 users、passwords)内容直接拼进查询结果;
• 若应用连接的是高权限用户,且未做列级过滤,SELECT 本身已足够泄露全部数据;
• 某些数据库(如 MySQL 5.7+)支持 SELECT ... INTO OUTFILE,配合文件读写权限可导出任意可读文件。
如何按功能切分数据库用户并配最小权限?
不要用一个账号跑全站。按模块/操作类型建独立用户,例如:
• 前端只读接口 → 用户 app_reader,仅授予 SELECT 权限,且限定在 public schema 下指定视图(如 v_product_list),不给基表权限;
• 后台管理接口 → 用户 admin_writer,允许 INSERT/UPDATE/DELETE,但仅限 admin_logs、settings 等业务相关表;
• 定时任务账号 → 用户 job_user,只允许执行预定义的存储过程(如 proc_cleanup_old_orders),禁止直接表访问;
• 所有用户禁止 GRANT OPTION,禁用 FILE、PROCESS、SUPER 等高危权限。
pg_hba.conf 或 my.cnf 中的网络限制是否算权限控制?
不算,那是访问控制层,和权限模型无关。但必须配合使用:
• PostgreSQL 的 pg_hba.conf 应限制 app_reader 只能从应用服务器 IP 连接,且强制 hostssl;
• MySQL 的 bind-address 和 skip-networking 配合 CREATE USER 'app_reader'@'10.20.30.%' 才有效;
• 如果数据库暴露在公网或 Docker 默认桥接网段(如 172.17.0.0/16),再细的 SQL 权限也形同虚设;
• 注意:MySQL 8.0+ 的角色(ROLE)可简化权限分配,但角色本身仍需显式 GRANT 给用户,不能自动继承。
为什么视图(VIEW)比直接授权基表更安全?
因为视图可天然实现列裁剪与行过滤:
• 创建 CREATE VIEW v_user_public AS SELECT id, username, created_at FROM users WHERE status = 'active';,然后只对 v_user_public 授 SELECT;
• 即使注入成功,攻击者最多拿到这个视图里的字段,无法触达 password_hash、email 等敏感列;
• PostgreSQL 中还可配合 SECURITY DEFINER 视图,在视图内硬编码 WHERE tenant_id = current_setting('app.tenant_id') 实现租户隔离;
• 注意:MySQL 视图默认是 SQL SECURITY DEFINER,若定义者是 root,视图执行时会以 root 权限运行——这反而危险,应显式设为 SQL SECURITY INVOKER。
最常被忽略的一点:应用代码里硬编码的数据库账号密码,往往比权限配置本身更容易泄露;一旦失守,所有精细权限设计都会归零。别只盯着 GRANT,先管住你的 .env 文件和 CI/CD 日志。

















