MongoDB通过自定义角色在admin库中创建并精确指定resource的db和collection来实现集合级权限控制;collection为空字符串表示作用于该库所有集合,为具体名称则仅限该集合。

MongoDB 本身没有“表”概念,只有“集合(collection)”,所谓“表级权限控制”实际是指对特定 collection 的细粒度操作授权——必须用自定义角色(customRole)配合精确的 resource 描述来实现,内置角色如 read 或 readWrite 默认作用于整个数据库,无法限制到单个集合。
为什么 db.createRole 必须在 admin 数据库执行?
MongoDB 将所有角色元数据统一存于 admin.system.roles 集合中,无论你为哪个业务数据库设计角色,创建动作都必须在 admin 下进行。否则会报错:not authorized on admin to execute command { createRole: ... }。
常见错误是先 use myappdb 再调用 db.createRole,结果权限不足;正确流程是:
- 连接后立即执行
use admin - 用具备
userAdminAnyDatabase或userAdmin角色的用户认证(比如你之前建的管理员) - 再运行
db.createRole(...)
resource 中 collection 为空字符串 vs 具体名称的区别
resource: { db: "myappdb", collection: "" } 表示该角色对 myappdb 下**所有集合**生效;而 collection: "users" 则只作用于 users 这一个集合——这是实现“表级”控制的关键开关。
容易踩的坑:
- 误写成
collection: "*"或collection: ".*":MongoDB 不支持通配符,会直接忽略该 privilege 条目 - 忘记加引号把
collection: users写成未定义变量:shell 会报ReferenceError: users is not defined - 给
collection: ""配了insert却没给createCollection权限:用户无法在空库中新建集合,哪怕有insert
如何让一个角色同时操作多个指定集合?
不能在一个 privilege 条目里写多个 collection 名,必须拆成多个独立条目。例如要允许用户读 orders 和 customers,但只写 orders 的日志:
db.createRole({
role: "order_analyst",
privileges: [
{ resource: { db: "sales", collection: "orders" }, actions: ["find", "aggregate"] },
{ resource: { db: "sales", collection: "customers" }, actions: ["find"] },
{ resource: { db: "sales", collection: "logs" }, actions: ["insert"] }
],
roles: []
})
注意:roles: [] 是显式声明不继承其他角色,避免意外获得额外权限;若省略,MongoDB 默认设为空数组,但显式写出更安全、可读性更强。
grantRolesToUser 和 createUser 的权限分配时机差异
如果你已存在用户,用 db.grantRolesToUser("alice", [{role:"order_analyst", db:"sales"}]) 是最稳妥的追加方式;而 db.createUser(...) 中的 roles 字段是**全量覆盖**——如果用户已有其他角色,这次创建会清空旧角色并只保留新指定的。
生产环境中建议统一用 grantRolesToUser 和 revokeRolesFromUser 增量管理,避免因覆盖导致权限丢失。另外,grantRolesToUser 必须在目标用户所属的数据库上下文中执行(比如用户角色绑定在 sales 库,就得先 use sales 再执行),否则会提示 not authorized to execute command。
真正难的不是写对那几行 db.createRole,而是理清资源边界:同一个角色能否跨库?能,但每个 privilege 必须单独声明 db;一个用户能否拥有不同库的多个角色?能,但每个角色必须在对应库名下声明——这些细节一旦错位,权限就静默失效,连 db.runCommand({connectionStatus: 1}) 都看不出问题在哪。











