mongodb集合级权限控制必须启用rbac并自定义角色,resource需同时指定db和collection,角色须在admin库创建,仅内置角色无法限制到单集合。

resource 明确限定到 db 和 collection 两级——仅靠内置角色(如 read、readWrite)做不到。
创建集合级角色必须用 createRole(),不能用内置角色
内置角色(如 read)作用域只能是整个数据库,即使你只给用户授了 read 角色并指定 db: "myapp",该用户也能读 myapp 下所有集合。真要限制到单个集合,必须手写角色:
use admin
db.createRole({
role: "inventoryReader",
privileges: [{
resource: { db: "myapp", collection: "inventory" },
actions: ["find"]
}],
roles: []
})
-
resource字段必须同时包含db和collection,缺一不可;留空collection或设为""等同于全库 - 角色必须在
admin数据库中创建,否则无法被跨库授予 - 不要把
createCollection权限单独授予集合级角色——用户能建集合却没权限读,容易引发误操作或权限混乱
给用户授集合级角色时,db 参数指目标数据库,不是认证库
用户可以在任意数据库下创建,但其权限可跨库生效。关键在于 createUser() 中 roles 数组里的 db 字段,它决定该角色作用于哪个数据库的资源:
将 WCAG 2 AA 无障碍标准应用于设计系统、UI 组件和网页——通过可运行的验证器进行对比度计算,采用设计 token 模式使颜色天生可访问,设定排版和焦点状态规则,并提供语义检查清单。适用于构建或审查 UI。
use admin
db.createUser({
user: "stock_analyst",
pwd: "xxx",
roles: [
{ role: "inventoryReader", db: "admin" }, // 注意:这里 db 是角色定义所在库,不是数据所在库
{ role: "ordersReader", db: "admin" }
]
})
- 上面例子中,
inventoryReader角色本身定义在admin库,但它实际管控的是myapp.inventory集合——这个绑定关系写死在createRole()的resource里 - 用户认证时用的
--authenticationDatabase admin,和权限生效的数据库无关 - 如果用户需跨多个数据库访问不同集合,就在
roles数组里叠加多个角色,每个角色的resource各自指向对应db+collection
验证权限是否生效:用 db.runCommand({connectionStatus: 1}) 查当前会话角色
连接后执行命令,返回的 authInfo.roles 会列出已激活角色及其作用域,但不会展开显示具体 resource 细节。最直接的验证方式是实操测试:
- 尝试
db.inventory.find()→ 应成功 - 尝试
db.orders.find()→ 应报错not authorized on orders to execute command { find: "orders", ... } - 注意:即使用户对
orders集合有find权限,若未显式授予listCollections,执行show collections仍会失败——这是常见盲区
集合级权限不等于字段级权限,敏感字段仍需额外防护
resource: { db: "myapp", collection: "users" } 只控制“能不能读这个集合”,不控制“能不能读其中的 ssn 字段”。如果集合里混存了 PII(如身份证号、手机号),仅靠集合级控制远远不够:
- MongoDB 原生不支持字段级访问控制(FLAC),
$redact聚合阶段可做运行时过滤,但需在每次查询中手动加入,且无法防止直连绕过 - 生产环境涉及敏感字段,建议前置加一层服务层(如 Hasura、GraphQL API)做字段策略拦截,或用应用逻辑做投影过滤(
projection) - 集合级控制 + 字段级脱敏 + 网络层 IP 白名单,才是较完整的纵深防御组合
createRole() 中那个看似简单的 resource 对象——它必须精确到库和集合两级,且角色必须建在 admin 库;任何一处松动(比如漏写 collection、错放角色库、或混淆认证库与资源库),都会让限制形同虚设。










