graphql网关只需对业务库(如todo、blog)的readwrite权限,须在admin库创建用户并指定authsource=admin,禁用readwriteanydatabase以防越权操作。

GraphQL网关需要什么权限?
GraphQL网关本身不存数据,但它会代表前端发起 find、findOne、insertOne、updateOne、deleteOne 等操作。它不需要 dbAdmin 或 userAdmin 这类管理权限,也不该用 root 或 readWriteAnyDatabase——这些是运维账号的范畴。
真实场景里,网关只应访问 1–2 个业务库(比如 todo、blog),且仅需对其中集合做标准 CRUD。权限必须精确到库+动作,否则等于裸奔。
用 createUser 创建最小权限账号
别在 admin 库以外的地方创建网关用户——MongoDB 的角色绑定依赖 db 字段,且所有内置角色(如 readWrite)都要求显式指定目标库名。
假设你的 GraphQL 后端只读写 todo 库,执行以下命令:
use admin
db.createUser({
user: "graphql-gateway",
pwd: "your_strong_password_here",
roles: [
{ role: "readWrite", db: "todo" }
]
})
注意几点:
-
use admin是必须的——只有admin库支持跨库角色定义 -
roles数组里不能混用不同db;如果网关还要操作users库,就加第二项{ role: "readWrite", db: "users" } - 密码不能弱,尤其避免与开发环境共用;生产环境建议用密钥管理服务注入
- 创建后立刻测试:
mongosh "mongodb://graphql-gateway:your_strong_password_here@localhost:27017/todo",看能否db.todos.find().limit(1)
为什么不用 readWriteAnyDatabase?
这个角色看起来省事,但它允许账号对任意数据库执行写操作——包括 admin、config、local。一旦 GraphQL 解析器逻辑出 bug(比如误把用户输入拼进 collection 名),就可能触发 db.getSiblingDB("admin").system.users.drop() 这类灾难性调用。
更现实的风险是:攻击者通过 GraphQL 注入点(如未校验的 collectionName 参数)绕过业务层,直接命中 MongoDB 命令。权限越宽,爆炸半径越大。
所以:
-
readWriteAnyDatabase只给 DBA 工具账号,不给应用 - 网关连接字符串中明确指定
authSource=admin,否则驱动可能默认去业务库找用户凭证 - 连接池初始化时加
authMechanism=SCRAM-SHA-256,避免旧版机制被降级利用
连接驱动时要传哪些参数?
以 Go 的 mongo-go-driver 为例,URI 必须包含认证源和数据库名:
mongodb://graphql-gateway:your_strong_password_here@localhost:27017/?authSource=admin&authMechanism=SCRAM-SHA-256
关键点:
-
authSource=admin告诉驱动:用户信息在admin库查,不是在你要操作的todo库里 - 不要在 URI 末尾硬编码
/todo——那只是默认数据库,不影响权限校验;权限由createUser时声明的db字段决定 - Node.js 的
mongoose同理,需在connect选项里显式写authSource: 'admin' - 若用副本集,URI 中 host 列表必须包含主节点,或启用
directConnection=false让驱动自动发现
最常被忽略的是 authSource 缺失导致“Authentication failed”——错误日志里不会明说缺了它,只会报凭据无效。











