MongoDB权限生效需角色定义的db字段、用户认证时的authenticationDatabase及操作上下文三者严格一致,否则即使启用authorization也会报Unauthorized。

直接启用 security.authorization: enabled 并创建用户,不等于权限就生效了——绝大多数“Unauthorized”错误,根源不在认证开关没开,而在角色定义与实际操作的数据库上下文不匹配。
角色定义时 resource.db 和实际 use 的库必须一致
MongoDB 的权限检查严格绑定当前会话的默认数据库(即你执行 use myapp 后的上下文)。即使你在 admin 库里创建了角色,如果用户在 myapp 库认证(db.auth({user:"u", db:"myapp"})),那这个角色根本不会被加载。
- 错误写法:
use admin→ 创建角色授权{ db: "myapp", collection: "orders" },但用户用mongosh -u u -p p --authenticationDatabase myapp连接 → 权限不生效 - 正确做法:角色定义中的
db字段,必须和用户认证时指定的--authenticationDatabase(或db.auth()的第二个参数)完全一致 - 验证当前会话权限范围:运行
db.runCommand({connectionStatus: 1}),看返回中authInfo.roles列表和每个角色的db字段是否匹配你的操作目标库
跨库读写必须拆成多个 role 条目,不能靠单个 privilege 覆盖
一个 privilege 只能声明一个 resource,想让一个用户既能读 sales 又能写 logs,必须在 createUser() 的 roles 数组里显式列出多个角色项,而不是指望一个自定义角色包揽所有库。
- 可行:
{ role: "read", db: "sales" }, { role: "readWrite", db: "logs" } - 不可行:只给一个角色
{ resource: { db: "sales" }, actions: ["find"] },然后期望它对logs也生效 - 注意:内置角色如
readAnyDatabase确实能跨库,但它属于高危权限,仅限运维账号,绝不该用于应用服务账号
自定义角色必须在 admin 库创建,且 privileges 中的 resource.db 必须真实存在
db.createRole() 命令只能在 admin 数据库下执行,但其中每个 resource.db 不需要提前建库——MongoDB 允许为尚未创建的库授权。真正踩坑的是资源路径写错,比如把 collection: "users" 写成 collection: "user",或者漏掉 collection 字段却想限制集合级操作。
- 最小可用示例:
use admin→db.createRole({ role: "appReader", privileges: [{ resource: { db: "myapp", collection: "orders" }, actions: ["find"] }], roles: [] }) - 集合级权限必须明确写出
collection;库级权限(如索引管理)用{ db: "myapp", collection: "" }或{ db: "myapp", collection: "system.indexes" } - 创建后立即验证:
db.getRole("appReader", { showPrivileges: true }),确认返回的privileges结构和你预期一致
最容易被忽略的一点:权限生效的前提是连接字符串里 --authenticationDatabase 参数值,必须和你分配角色时写的 db 字段、以及用户所属的角色定义所在库三者严格一致。差一个字母,就会静默拒绝所有操作。


















