不能直接用root角色给开发人员,因其隐式含__system权限可绕过库级隔离,导致跨库误删、查看所有数据库结构及用户列表、修改系统集合等高危操作,严重威胁数据安全。

为什么不能直接用 root 角色给开发人员?
开发人员连上数据库后执行 db.runCommand({listDatabases: 1}) 或 db.getSiblingDB("admin").system.users.find(),就可能看到所有数据库结构、用户列表甚至密码哈希(取决于版本和配置)。root 角色允许跨库执行任意操作,包括删除系统集合、修改用户权限、绕过审计日志——这在开发环境里极易演变成误操作,在测试或预发环境里则可能被横向利用。
db.createUser() 必须限定 db 和 role 范围
创建用户时,角色绑定必须精确到具体数据库和集合,不能依赖模糊继承。常见错误是只写 {role: "readWrite", db: "myapp"},但没意识到该角色默认允许对 myapp 下所有集合做 insert/update/remove,而实际开发中往往只需要操作 users 和 orders 两个集合。
- 只读场景:用
{role: "read", db: "myapp"},但若需聚合查询,得额外确认read角色是否含aggregate权限(MongoDB 6.0+ 默认包含,5.x 需显式添加) - 写入限制:不要直接赋
readWrite,改用自定义角色,例如只允许对logs集合执行insert,禁止find或delete - 跨库访问:开发人员若需读取
config库的分片信息,应单独创建角色并仅授予clusterMonitor,而非把myapp用户加到admin库
开发环境禁用 localhost 异常绕过机制
MongoDB 默认允许未认证连接从 localhost 直接访问,这是为部署初期便利设计的,但在开发机多人共用或 CI/CD 流水线中极易被滥用。一旦 mongod 启动时绑定了公网 IP(如 Docker 容器未设 --bind_ip 127.0.0.1),这个后门就失效且不可控。
- 确认配置文件中
net.bindIp明确设为127.0.0.1或内网地址,不写0.0.0.0 - 启动时加参数
--bind_ip 127.0.0.1 --port 27017,比依赖配置文件更可靠 - 检查
security.authorization是否为enabled,即使开发环境也别关——延迟启用只会让权限逻辑在上线前暴露不出问题
权限调试时别信 show users 的输出
show users 只显示当前数据库下的用户,但角色权限可能来自其他库(比如 admin 库定义的角色被赋予了 myapp 库的用户)。真正影响权限的是角色定义里的 privileges 数组,不是用户创建语句表面写的 roles。
- 查权限实际生效范围:连接后运行
db.runCommand({connectionStatus: 1}).authInfo.authenticatedUserRoles - 验证某操作是否被允许:用目标用户账号连上,直接试
db.mycollection.findOneAndDelete(...),看返回Unauthorized还是具体错误 - 避免角色嵌套过深:一个角色引用另一个角色,再引用第三个……最终权限链超过 3 层时,
getRole输出会截断,得用db.runCommand({rolesInfo: {role: "xxx", db: "admin", showPrivileges: true}})展开全量
最小权限不是删掉所有权限,而是让每个操作都有明确归属;开发人员最常踩的坑,是把“能跑通”当成“权限正确”,直到上线后发现审计日志里出现不该有的 dropDatabase 记录才回头查。











