必须在admin数据库创建角色才能跨库授权,因mongodb硬性规定仅admin库支持定义跨库资源;非admin库创建的角色权限被严格限制在本库内,且跨库resource条目会被静默忽略。

必须在 admin 数据库中创建角色,否则无法跨数据库授权。 其他数据库里创建的角色权限天然受限于该库边界,连 dbAdmin 都不能操作别的库——这是 MongoDB RBAC 的硬限制,不是配置疏漏。
为什么只能在 admin 数据库创建跨库角色
MongoDB 的角色作用域由创建时的数据库决定:admin 是唯一被允许定义“集群级”或“任意数据库级”资源的角色宿主。你在 myapp 库里执行 db.createRole(),哪怕在 actions 里写上 {"database": "otherdb", "collection": "coll"},MongoDB 也会静默忽略该 resource 条目,只保留当前库范围内的权限。
验证方式:用 db.runCommand({rolesInfo: {role: "my-role", db: "admin"}}) 查看实际生效的 privileges,会发现跨库 resource 已丢失。
db.createRole() 中跨库 resource 的写法要点
在 admin 数据库中调用时,resources 数组必须显式声明目标数据库名,且不能省略 collection 字段(即使想授权整个库):
use admin
db.createRole({
role: "crossdb-reader",
privileges: [{
resource: { database: "orders", collection: "" }, // ← 空字符串表示“所有集合”
actions: ["find"]
}, {
resource: { database: "logs", collection: "error_log" },
actions: ["insert", "find"]
}],
roles: [] // 不继承其他角色,避免隐式越权
})
-
collection: ""是关键:填"*"或留空数组会报错;填""才被识别为通配 - 不能写
resource: { database: "orders", collection: "*" }—— MongoDB 不支持*通配符语法 - 若需跨库执行命令(如
listDatabases),必须额外加一条resource: { cluster: true }的 privilege
分配角色给用户时的常见错误
用户本身可以在任意数据库创建(比如在 test 库里 db.createUser()),但绑定跨库角色时,必须用 db.grantRolesToUser() 在 admin 库上下文中执行:
use admin
db.grantRolesToUser("app-user", [{ role: "crossdb-reader", db: "admin" }])
- 如果误在
orders库里执行db.grantRolesToUser(),MongoDB 会提示RoleNotFound,因为它只在当前库的system.roles查找角色(而角色实际存在admin.system.roles) - Atlas 用户界面里分配角色时,角色列表默认只显示当前项目下
admin中定义的角色,但 UI 不提示“必须选 admin 库”,容易点错 - 自托管部署中,如果启用了
authenticationRestrictions,还要确认 IP 白名单允许访问所有目标数据库的 mongos/mongod 节点
最容易被忽略的是:角色创建后,用户连接时仍需显式认证到 admin 数据库(mongo -u user -p pass --authenticationDatabase admin),否则即使角色已绑定,权限也不生效——因为认证数据库决定了权限解析的起点。











