MongoDB中角色继承严格限定于创建库:仅admin库中创建的角色可跨库继承,非admin库角色只能继承本库角色,否则权限不可见或报错。

用 db.createRole() 在指定数据库中创建角色
自定义角色必须在某个具体数据库中创建,角色名和数据库名共同构成唯一标识。比如想让角色只对 myapp 数据库生效,就得先 use myapp,再执行创建操作;若在 admin 数据库中创建,则该角色可作用于集群级资源(如所有数据库、特定 collection 名跨库匹配等)。
常见错误是直接在 test 或未认证的连接下运行 db.createRole(),结果报错 not authorized on myapp to execute command createRole。这是因为创建角色需要 createRole 权限,通常由 userAdmin 或 userAdminAnyDatabase 角色授予。
- 必须用具备
createRole和grantRole权限的用户连接,例如userAdminAnyDatabase(需在admin库认证) -
privileges数组里每个对象的resource必须明确指定db字段;collection 级权限要写collection: "orders",库级权限则设collection: "" - 不要在
privileges中混用跨库资源(如db: "otherdb")——除非角色建在admin库,否则 MongoDB 会拒绝
权限冲突时以“最高权限”为准,但不自动合并
一个用户可被分配多个角色,MongoDB 不做权限“求并集”,而是按操作粒度取各角色中该操作的最高级别许可。比如角色 A 给 read,角色 B 给 readWrite,那用户对同一 collection 就有 readWrite 权限;但若角色 A 允许 bypassDocumentValidation,角色 B 没提这项,则用户仍拥有该绕过权限。
容易踩的坑是误以为多个角色能“叠加”出新能力。例如:角色 X 授予 find,角色 Y 授予 update,但两者都限定在不同 collection 上(X 对 users,Y 对 logs),那么用户确实能分别操作这两个 collection —— 但这不是“合并”,而是各自生效。一旦某个 collection 没被任一角色覆盖,就无权访问。
- 内置角色如
readWrite和自定义角色同时分配时,后者不会覆盖前者已有的权限,但可能补充缺失的操作(如加collMod) - 若两个角色对同一 resource 的同一 action 出现显式拒绝(比如通过
deniedActions),MongoDB 当前版本(7.0+)不支持 deny 语义,所以实际仍以 grant 为准 - 在 Atlas 中,角色更新有最多 30 秒延迟,
mongosh执行完db.createRole()后立刻测试可能失败,建议等半分钟再验
继承角色只能来自同一数据库,admin 库例外
roles 字段用于声明继承关系,但限制很紧:普通数据库(如 myapp)里的角色,只能继承本库中其他角色;只有 admin 库的角色,才能继承其他任意数据库的角色(包括其他业务库或 admin 自身)。
典型误操作是,在 reporting 库里创建角色时,试图继承 admin 库的 clusterMonitor,结果报错 Role not found。这不是路径写错,而是设计限制 —— 非 admin 角色无法跨库继承。
- 若需复用权限,可在
admin库统一建基础角色,再让业务库角色通过admin角色间接继承(即:业务库角色 → admin 库角色 → 内置角色) -
db.grantRolesToRole()可动态追加继承关系,比删重建更安全,尤其在线上环境 - 删除父角色前,务必检查
db.getRole("xxx", {showPrivileges: true})输出中的inheritedRoles,避免子角色失效
Atlas 和自托管部署的关键差异点
在 Atlas 中,你不能直接连到 mongod 执行 db.createRole();所有角色变更必须走 Atlas CLI、API 或 UI。否则 Atlas 会在几秒内检测并回滚你的修改,日志里只显示 Custom role change rolled back,没有更多线索。
而自托管部署(比如你自己的 EC2 实例)则完全依赖 mongosh 或驱动调用 db.createRole(),且角色信息存于 admin.system.roles 集合 —— 这意味着备份恢复后,角色不会自动回来,必须单独导出/导入 system.roles。
- Atlas 项目默认最多 100 个自定义角色,超限需调用
POST /api/atlas/v2/projects/{projectId}/limits提升配额 - 自托管部署没硬性数量限制,但角色过多会影响认证阶段的权限解析性能(尤其带复杂 resource pattern 时)
- Ops Manager 托管的部署中,角色同步依赖
Synced: Yes设置;一旦关掉,该角色会在下次同步周期被彻底清除,不可逆
listCollections 就能查所有集合,却忘了它还需要对应数据库的 find 权限才能读取 system.namespaces;这类组合权限问题,往往要靠反复试错 + db.runCommand({connectionStatus: 1}) 查当前会话实际拥有的 actions 才能定位。

















