readwrite不能当只读用,因其默认含insert、update、delete、drop等全部写权限,易导致误写;只读必须用read角色并显式指定db字段,且认证库须与权限作用域一致。

“readWrite”不是只读角色,它是读写角色;要配只读权限,必须用 read 角色,不能混淆。
为什么 readWrite 不能当只读用
readWrite 角色默认包含 insert、update、delete、drop 等全部写操作权限,哪怕你只打算“暂时不写”,只要角色存在,就等于开了写通道。生产环境误授 readWrite 是高频事故源。
- 执行
db.collection.insertOne({})不报错 → 权限已生效,但不符合只读预期 - 应用配置泄漏或脚本误触发写操作时,数据可能被意外覆盖或清空
-
readWrite还隐含create权限,能新建集合,进一步扩大风险面
正确创建只读用户:必须用 read 角色 + 显式 db 字段
只读用户必须在目标业务数据库上下文中创建,并显式指定 roles: [{ role: "read", db: "your_db_name" }]。漏掉 db 字段或在 admin 库下执行,都会导致权限不生效。
- 错误做法:
use admin后运行db.createUser(...),即使db: "your_db_name"写对了,认证库仍是admin,连接时需额外指定--authenticationDatabase admin,极易出错 - 推荐做法:先
use your_db_name,再执行db.createUser(),此时db字段仍建议保留(不省略),避免未来迁移或脚本复用时歧义 - 密码明文传入即可,MongoDB 6.0+ 自动按
SCRAM-SHA-256加密存储,无需手动哈希
连接时总提示 Authentication failed?检查认证库是否匹配
用户是在 myapp 库创建的,连接命令就必须带 --authenticationDatabase myapp。MongoDB 不会自动推断认证库,它只认 db 字段声明的库作为权限作用域,也作为默认认证库。
- 错误示例:
mongosh "mongodb://reporter:pwd@localhost:27017/myapp"→ 缺少?authSource=myapp或--authenticationDatabase myapp - 正确示例:
mongosh "mongodb://reporter:pwd@localhost:27017/myapp?authSource=myapp" - 驱动连接字符串同理:Python 的
uri="mongodb://.../myapp?authSource=myapp",Node.js 的authSource: "myapp"选项不能少
read 角色访问限制:系统集合默认不可读
read 角色只允许读业务集合,对 system.users、system.roles 等元数据集合无权限。执行 db.system.users.find() 会明确报错:not authorized on myapp to execute command { find: "system.users", ... }。
- 这不是配置失败,是 MongoDB 的安全设计——业务用户不该看到权限系统内部结构
- 调试时如需查用户列表,必须由管理员临时在
admin库中授予viewUserManagement角色,且仅限单次诊断 - 生产环境长期开启该权限 = 变相暴露账号体系,禁止这么做
最容易被忽略的是认证库与权限作用域的绑定关系:它们由 db 字段决定,而非当前 shell 的 use 语句——后者只影响后续命令默认作用库,不改变用户元数据存储位置或认证逻辑。











