mongodb权限由db.createrole()和db.createuser()动态绑定资源范围实现,角色必须在admin库创建且用户认证库决定权限加载范围,权限检查严格按会话认证库和显式声明的db/collection匹配。

MongoDB 的权限与角色不是靠“设计文档模型”实现的,而是靠 db.createRole() 和 db.createUser() 在运行时动态绑定资源范围(db + collection)生效的。所谓“文档模型”,本质是把策略翻译成可执行的 Shell 命令,不是产出 JSON Schema 或 Markdown 文档。
db.createRole() 中 resource 必须显式声明 db 和 collection
权限永远不自动跨库、不自动匹配同名集合。比如你给角色 appReader 分配了 { db: "myapp", collection: "orders" } 的 find 权限,但应用连的是 test 库并执行 db.orders.find() —— 直接报 Unauthorized。
-
collection: ""表示该库下所有集合,但仅限指定的db -
collection: "system.views"这类特殊集合必须显式写出,不能靠通配 - 想让一个角色读
A库、写B库?得在同一个privileges数组里写两条独立条目,不能合并
角色必须在 admin 库创建,且用户认证库决定权限加载范围
你在 myapp 库执行 db.createRole(),这个角色只在 myapp 库内可见,无法被其他库的用户引用;只有在 admin 库创建的角色,才能作为跨库权限载体。
- 用户在哪一个库调用
db.auth(),就只加载该库下分配的角色 —— 即使你给用户写了{ role: "read", db: "logs" },但db.auth({ user: "u", db: "myapp" }),那logs的角色完全不生效 - 用户创建时的
roles数组里,每个{ role, db }都必须指向真实存在的数据库,否则登录失败或权限缺失 -
readAnyDatabase等内置角色,只在admin库分配才有效;在其他库分配等于空转
不要用 $ref 做权限模型,那是业务关联不是 RBAC
有人把角色、权限、用户三张表用 $ref 字段互相引用,这是业务层多对多关系建模,和 MongoDB 的 RBAC 完全无关。RBAC 不读这些文档,它只认 admin.system.roles 和 admin.system.users 里的配置。
-
$ref是 Mongoose 或应用层模拟关系的手段,不影响服务端权限校验 - 真正控制数据访问的是
db.runCommand({ connectionStatus: 1 })返回的authInfo.privileges,不是你存了几条roles文档 - 如果靠
$ref控制“谁能看这条订单”,说明你没启用授权,或者权限没配对 —— 这属于逻辑漏洞,不是设计选择
最容易被忽略的一点:权限检查发生在命令执行前,且严格按当前会话的认证库 + 角色定义做匹配。任何试图绕过 db 显式声明、依赖命名约定或应用层过滤的做法,都会在真实部署中突然失效。











