创建只读角色并绑定到数据库最小权限的第一步是避免直接使用read或readWrite内置角色,必须显式声明resource为{db:"appdb",collection:"users"}并限定actions为["find"],否则权限将作用于整个数据库,违背最小权限原则。

如何创建只读角色并绑定到数据库
最小权限的第一步是避免直接用 read 或 readWrite 内置角色,它们默认作用于整个数据库。你需要显式声明资源范围和操作限制。
例如,只想让某角色查 users 集合的指定字段,不能删改、不能看 orders:
db.createRole({
role: "users_reader",
privileges: [{
resource: { db: "appdb", collection: "users" },
actions: ["find"]
}],
roles: []
})
注意:resource 必须精确到 db 和 collection,留空或写 {} 会匹配全部数据库,失去最小化意义。MongoDB 不支持字段级权限(如只允许返回 name 字段),这得靠应用层过滤或聚合管道控制。
为什么不能直接给用户 assignRole 内置角色
内置角色如 read 默认作用域是「当前认证数据库」,但用户连接时可能用 admin 库认证,而操作的是 appdb ——这时 read 只在 admin 生效,对 appdb 无权限,报错 not authorized on appdb to execute command。
解决方法只有两个:
- 创建自定义角色时,
resource显式写死{ db: "appdb", collection: "xxx" } - 或用
db.grantPrivilegesToRole()后续追加权限,但依然要指定具体db
别依赖 roles: [{ role: "read", db: "appdb" }] 这种写法——它只是把内置角色“复用”进来,本质还是把整个 appdb 的读权限给了用户,不符合最小原则。
如何限制用户只能执行特定聚合管道
MongoDB 没有“仅允许某条聚合命令”的机制,但可通过 actions: ["find"] + 视图(view)间接实现。视图本质是预定义的聚合管道,用户查视图等价于执行固定逻辑。
实操步骤:
- 在
appdb创建视图:db.createView("active_users", "users", [ { $match: { status: "active" } } ]) - 给角色授予权限:只对
active_users视图有find权限,不对原始users集合授权 - 用户查询
db.active_users.find()可行,查db.users.find()直接拒绝
注意:视图不支持写操作,也不能嵌套视图。如果业务需要动态条件,仍需靠应用层校验或使用 $redact 在管道内做行级过滤,但这属于运行时控制,不改变权限模型。
role 创建后权限不生效的常见原因
最常踩的坑是忘了刷新权限缓存或连错数据库:
- 角色必须在
admin数据库创建(除非用--auth启动且明确指定了roles的db) - 用户必须在
admin中创建,并用db.createUser({ ..., roles: [{ role: "users_reader", db: "admin" }] })绑定——这里的db: "admin"是指角色定义所在的库,不是目标操作库 - 连接时认证数据库必须是
admin(即mongo -u user -p pass --authenticationDatabase admin),否则角色加载失败
权限变更后,已有连接不会自动更新,需重连或等缓存过期(默认 30 分钟),测试时务必新开 shell 连接验证。











