MongoDB需用createRole在目标库中定义集合级角色,privileges须精确指定db和collection;授权时必须use对应库再执行grantRolesToUser,并显式声明db字段;单角色可组合多集合不同权限;结构变更操作需单独授权。

如何用 createRole 定义只对特定集合有读写权限的自定义角色
MongoDB 默认的内置角色(如 read、readWrite)作用域是整个数据库,无法限制到单个集合。要实现集合级读写分离(比如只允许读 users、只允许写 logs),必须用 createRole 手动定义,并在 privileges 中显式指定 resource 的 db 和 collection 字段。
关键点:角色必须在目标数据库下创建(不是 admin),且 resource 中的 collection 名必须精确匹配,空字符串 "" 表示“所有集合”,不能省略或写错。
例如,在 myapp 库中创建一个仅对 orders 集合有读权限的角色:
use myapp
db.createRole({
role: "ordersReadOnly",
privileges: [{
resource: { db: "myapp", collection: "orders" },
actions: ["find"]
}],
roles: []
})
为什么给用户授予权限时必须指定数据库上下文
执行 db.grantRolesToUser 时,角色名和数据库名是绑定的。即使角色定义在 myapp,如果在 admin 库下运行授权命令,MongoDB 会去 admin 下找该角色——找不到就报错 RoleNotFound。
常见错误现象:no role found for name: "ordersReadOnly" in database "admin",本质就是授权时用错了 use 数据库。
正确做法:
- 先
use myapp - 再运行
db.grantRolesToUser("app_user", [{ role: "ordersReadOnly", db: "myapp" }])
注意:db 字段在 grantRolesToUser 中必须与角色所在数据库一致,不能简写为 "." 或省略。
如何组合多个集合的不同读写权限(读 A 写 B)
一个角色可以包含多条 privilege,每条指向不同集合,各自声明 actions。不需要拆成两个角色,也不需要继承。
例如,让角色同时具备:products 只读、inventory_updates 可写、audit_log 可插入但不可查:
use inventory_db
db.createRole({
role: "stockOperator",
privileges: [
{ resource: { db: "inventory_db", collection: "products" }, actions: ["find"] },
{ resource: { db: "inventory_db", collection: "inventory_updates" }, actions: ["insert", "update", "remove"] },
{ resource: { db: "inventory_db", collection: "audit_log" }, actions: ["insert"] }
],
roles: []
})
性能影响很小——权限检查发生在每次操作解析阶段,不涉及集合扫描;但若 privileges 列表过长(>20 条),可能略微增加连接初始化开销。
使用 collMod 或 createIndex 等命令时权限是否自动包含
不包含。MongoDB 的集合级权限只覆盖 CRUD 和部分管理动作(如 collStats),但像 collMod、convertToCapped、createIndex 这类“集合结构变更”操作,需要额外授予 collMod 或 createIndex 动作,且必须明确写在对应集合的 resource 下。
容易踩的坑:
- 以为有
update权限就能建索引——实际会报not authorized on ... to execute command { createIndexes: ... } - 在
resource中把collection写成正则或通配符(如"user.*")——MongoDB 不支持,只认字面量名称 - 给
actions传了大小写错误的字符串,比如"Find"或"INSERT"——必须全小写
细粒度控制真正生效的前提,是彻底放弃“用一个角色包打天下”的思路,每个集合的每个必要操作都单独列明。这看起来啰嗦,但恰恰是权限不越界的关键。


















