直接配readwrite角色危险,因其内置drop权限且无法删减;须用自定义角色显式授权安全操作,如devwritenodrop,并确保authsource=admin。

直接给开发人员配 readWrite 角色是危险的——它默认包含 dropCollection 和 dropDatabase 权限,哪怕只连到 dev 库,也能误删整个库。必须用自定义角色显式剔除 drop 类操作。
为什么不能直接改 readWrite 角色
MongoDB 不支持“减法式授权”:你不能给用户授 readWrite 再禁掉 drop。权限模型是白名单制,readWrite 内置的 actions 是固定集合,无法动态删减。试图用 revokeRolesFromUser 剥离部分权限会失败,因为角色本身不可拆解。
- 所有内置角色(包括
readWrite)的 actions 都硬编码在服务端,客户端无法覆盖或 patch -
db.grantPrivilegesToRole()只能加权限,不能删;db.revokePrivilegesFromRole()在 6.0+ 才支持,但仅限自定义角色,且不适用于内置角色 - 若强行在
readWrite基础上叠加 deny 规则,MongoDB 完全忽略——它没有 deny 机制
正确创建无 drop 的开发角色(以 dev 库为例)
在 admin 库中执行以下命令,定义一个只含安全写操作的自定义角色:
use admin
db.createRole({
role: "DevWriteNoDrop",
privileges: [
{
resource: { db: "dev", collection: "" },
actions: [
"find", "insert", "update", "replace", "delete",
"createIndex", "dropIndex", "aggregate", "explain"
]
},
{
resource: { db: "dev", collection: "system.profile" },
actions: ["find"]
}
],
roles: []
})
-
collection: ""表示该库下所有普通集合(不含system.*),比逐个列集合更实用,也避免漏配 - 明确没列
dropCollection、dropDatabase、convertToCapped等高危动作,它们就不会生效 - 保留
delete是因开发常需清测试数据;如需彻底禁 delete,就从 actions 数组里删掉它 - 必须在
admin库运行,否则角色创建后其他数据库不可见
绑定用户时 authSource 必须显式指定
即使角色和用户都建在 admin 库,连接时仍可能认证失败——因为 MongoDB 默认在当前数据库查用户凭证,而不是 admin。
- 连接字符串必须带
?authSource=admin,例如:mongodb://dev_user:pass@localhost:27017/dev?authSource=admin - mongosh 命令行要加
--authenticationDatabase admin,否则连上dev库后执行db.auth()会报Unauthorized - Node.js 驱动中
auth选项的authSource字段不可省略,设为"admin" - 如果用户建在
dev库(不推荐),那authSource就得改成"dev",但角色必须也在同一库创建,否则权限不继承
真正容易被忽略的是:dropCollection 权限藏得深——它不在集合级 resource 下,而是属于数据库级 resource({ db: "dev", collection: "" } 不触发它,但 { db: "dev", collection: null } 或 { db: "dev" } 会)。所以只要 privileges 里 resource 的 collection 字段始终是非 null 值,drop 就不会意外启用。











