在admin库中执行db.createuser()并显式指定roles数组中每个角色的role和db字段,可实现跨库授权;若不在admin库执行,则db字段被忽略,导致权限失效。

直接在 admin 数据库中创建用户,并通过 roles 数组一次性指定多个 {role, db} 对,就能实现跨库授权。不需要为每个库单独连接、单独建用户。
用 db.createUser() 在 admin 库中声明多个数据库角色
必须切换到 admin 数据库执行,否则角色只会绑定到当前库(比如切在 test 库里执行,db: "prod" 这种配置会被忽略)。
-
use admin是强制前置步骤,不是可选 -
roles里每个对象都必须显式写全role和db字段,不能省略db - 角色名必须是 MongoDB 内置角色或已存在的自定义角色,比如
"readWrite"、"dbOwner"、"readAnyDatabase"等 - 示例:给用户
appuser同时授予orders库的读写、users库的只读、logs库的dbAdmin权限:
db.createUser({
user: "appuser",
pwd: "strongpass123",
roles: [
{ role: "readWrite", db: "orders" },
{ role: "read", db: "users" },
{ role: "dbAdmin", db: "logs" }
]
})
执行后,该用户登录时只需认证一次,就能按角色权限访问对应数据库,无需反复 use 切库再 db.auth()。
为什么不能在非 admin 库里创建跨库角色
因为 MongoDB 的角色作用域由创建时所在的数据库决定:db.createUser() 在哪个库运行,其 roles 中的 db 字段才被真正解析和持久化。
- 若在
test库执行db.createUser({roles: [{role:"readWrite", db:"prod"}]}),MongoDB 会把db: "prod"当作无效字段静默丢弃,实际只存了{role: "readWrite", db: "test"} - 错误现象:用户连上后能操作
test,但对prod执行db.collection.find()直接报not authorized on prod to execute command - 验证方式:用
db.getUser("appuser")查看返回的roles数组,确认每个项的db值是否符合预期
readWriteAnyDatabase 和手动列多个 {role, db} 的区别
前者是全局通配,后者是精确控制。生产环境强烈建议后者。
-
readWriteAnyDatabase属于 all-database 角色,必须在admin库授予,且一旦赋予,用户对所有现有及未来新建数据库都有读写权 —— 权限过大,违反最小权限原则 - 手动列出每个
{role, db}更安全:新增数据库时不会自动继承权限;权限变更只需改用户角色,不涉及重启或重配 - 性能无差异:权限校验走的是内存缓存的 role→privilege 映射,与角色数量关系不大
- 注意兼容性:
readWriteAnyDatabase在启用了authorization的分片集群中需配合clusterManager才能管理 config 库,而细粒度角色无此限制
常见权限失效场景与排查点
即使语法正确,用户仍可能遇到“not authorized”错误,重点检查以下三项:
- 服务启动时是否加了
--auth或配置文件中security.authorization: enabled?没开授权,所有createUser都白搭 - 客户端连接串是否指定
authSource=admin?例如mongodb://appuser:pass@host:27017/myapp?authSource=admin,否则默认从目标库(如myapp)查用户,找不到 - 用户密码含特殊字符(如
/、@、:)未 URL 编码?连接串里必须编码,但createUser()的pwd字段不用编码 - 副本集环境下,
db.createUser()必须在主节点执行;若误在从节点运行,命令会成功返回但实际未写入,因为从节点拒绝写操作
跨库授权本身不复杂,难的是权限边界意识和部署一致性 —— 每次增库、换角色、切环境,都要同步核对 db 字段和 authSource 配置,漏一处就全线不可用。











