只读用户可在任意数据库创建,但必须显式指定{role: "read", db: "testdb"}且连接时通过--authenticationdatabase testdb指定认证库;若服务未启用security.authorization: enabled,权限配置无效。

只读用户必须在目标数据库还是 admin 数据库创建?
必须先 use 到目标数据库(比如 testdb),再执行 createUser。MongoDB 的 read 角色作用域是「当前数据库」,不是全局生效;如果误在 admin 库下创建,用户仍无法读取 testdb —— 除非你显式指定 { role: "read", db: "testdb" },但此时仍需确保该用户认证时连接的是 testdb 或通过 --authenticationDatabase 指定正确认证库。
用 read 角色就能真正只读?常见越权操作有哪些
是的,read 角色默认只允许 find、listCollections、listIndexes 等操作,但要注意:
- 它不阻止用户执行
db.getCollectionNames()或db.collection.stats()—— 这些属于元数据读取,包含在read内 - 它不能防止用户读取
system.*集合(如system.users),除非你禁用该权限或使用自定义角色屏蔽 - 如果用户被错误赋予了
readAnyDatabase(仅限admin库),那他就可读所有数据库——这和单库read完全不同 - 某些驱动或工具(如 Compass)可能自动尝试
db.runCommand({connectionStatus: 1}),该命令需要monitor权限,read不包含它,会报错但不影响主业务
createUser 命令里 roles 字段怎么写才安全
最简且推荐的写法是直接绑定数据库级 read 角色,不混用其他角色:
use testdb
db.createUser({
user: "reporter",
pwd: "strongPassword123!",
roles: [{ role: "read", db: "testdb" }]
})
注意以下几点:
-
pwd必须是明文字符串(不是哈希),MongoDB 会自动 SCRAM 加密存储 -
roles是数组,哪怕只配一个角色也要写成[{...}] - 不要写
{ role: "read", db: "admin" }试图“绕过认证库”,这只会让用户能读admin库,而不是testdb - 如果未来要升级为读写,用
db.updateUser()替换整个roles数组,避免遗漏旧角色
连接时为什么提示 Authentication failed?
90% 是因为没指定认证库。即使用户是在 testdb 创建的,连接命令也必须带 --authenticationDatabase testdb:
mongosh "mongodb://localhost:27017/testdb" --username reporter --password strongPassword123! --authenticationDatabase testdb
否则默认走 admin 库认证,自然失败。Docker 或云服务中还常漏掉 --auth 启动参数,导致权限系统根本没启用——这时任何用户都等价于 root。
--auth 或配置文件中 security.authorization: enabled),否则所有 createUser 操作都只是存了个空壳,毫无约束力。











