MongoDB 5.0 不支持直接继承内置角色,必须通过 getRole 提取其 privileges 并手动合并到自定义角色中;创建时 privileges 需显式列出全部权限(含 system.profile 等特殊集合),roles 数组须为空,且角色需用 grantRolesToUser 显式授予用户。

直接继承内置角色失败:MongoDB 5.0不支持角色继承语法
MongoDB 5.0 的 createRole 不接受 roles 字段中填入内置角色(如 "readWrite"、"dbAdmin")作为“父角色”来继承——这会报错 "Cannot specify built-in role in roles array"。它只允许继承自用户自定义角色,内置角色必须显式展开权限再组合。
正确做法:用 db.runCommand({ getRole: ... }) 提取内置角色的权限清单
你需要手动查出内置角色包含哪些 privileges 和 roles(注意:后者仅指其他自定义角色),再把它们合并进新角色定义里:
db.runCommand({
getRole: "readWrite",
db: "myapp",
showPrivileges: true,
showBuiltinRoles: true
})
重点提取返回中的 privileges 数组(含 resource + actions),以及 inheritedRoles(如果有嵌套自定义角色)。
- 务必指定
db参数,否则可能返回空或跨库错误 -
showBuiltinRoles: true才能看清该角色是否依赖其他内置角色(如readWrite本身不继承,但dbOwner会列出readWrite和dbAdmin) - 返回里的
actions是字符串数组,比如["find", "insert", "update"],不能漏掉大小写
创建扩展角色时:合并权限 + 显式添加新权限
假设你想在 readWrite 基础上增加对 system.profile 的读权限,不能写 "roles": ["readWrite"],而要:
- 从
getRole结果中复制全部privileges - 追加一条新 privilege:
{ resource: { collection: "system.profile" }, actions: ["find"] } -
role名必须小写字母+数字+下划线,不能含点或大写 - 执行
createRole时,db必须与目标数据库一致(不是admin,除非是集群级角色)
示例片段(在 myapp 库执行):
db.runCommand({
createRole: "readWriteWithProfile",
privileges: [
// ……此处粘贴 getRole("readWrite") 返回的全部 privileges,
// 再加上下面这一条:
{ resource: { collection: "system.profile" }, actions: ["find"] }
],
roles: [] // 留空,不填内置角色
})
权限生效前必须显式授予用户,且注意作用域限制
新建角色不会自动绑定到任何用户;你得用 grantRolesToUser 手动授权,而且角色只在创建它的数据库生效:
db.grantRolesToUser("appuser", [{ role: "readWriteWithProfile", db: "myapp" }])
- 如果用户需要跨库权限,必须在每个目标库分别创建对应角色(或使用
admin库的集群角色,但需clusterAdmin权限) - 修改角色后,已登录连接不会实时刷新权限,需重新认证或等待连接超时重连
-
system.*集合权限(如system.profile)默认被多数内置角色排除,必须手动加,这是最容易漏的点
真正麻烦的不是语法,而是 MongoDB 把“角色”和“权限”两层做了硬性隔离:内置角色只是预设模板,一旦想微调,就得亲手拆解、重组、验证——少一个 resource 字段或拼错 collection 名,权限就静默失效。











