最简方式是在目标数据库中执行db.createuser()并指定roles:["read"],注意角色作用域限于当前库,需显式声明db字段;read角色不访问系统集合,跨库只读须为各库单独授权,创建后须用典型操作验证权限。

如何用 db.createUser() 创建只读用户
直接在目标数据库中运行 db.createUser(),指定 roles 为 ["read"],这是最简方式。注意:角色作用域是当前数据库,不是全局。
常见错误是误在 admin 数据库下执行却期望对其他库生效——read 角色不跨库,必须切换到目标库再创建:
use myapp
db.createUser({
user: "reporter",
pwd: "s3cureP@ss",
roles: [{ role: "read", db: "myapp" }]
})
- 不要省略
db字段(即使和当前库同名),显式声明更安全 -
pwd在 MongoDB 6.0+ 默认启用 SCRAM-SHA-256,旧客户端可能需降级认证机制 - 如果用 MongoDB Atlas 或 Ops Manager,密码策略可能强制复杂度,本地测试时可先绕过
为什么 read 角色不能访问系统集合
read 内置角色默认不包含 system.* 集合的读权限,比如 system.users、system.roles。执行 db.system.users.find() 会报错:not authorized on myapp to execute command { find: "system.users", ... }
这不是 bug,而是设计使然:系统集合属于元数据层,普通业务用户不该接触。若真需查用户列表(例如调试),只能由管理员临时授予 viewUserManagement 角色,且必须在 admin 库中授:
use admin
db.runCommand({
grantRolesToUser: "reporter",
roles: [{ role: "viewUserManagement", db: "admin" }],
writeConcern: { w: "majority" }
})
- 该操作必须由拥有
userAdminAnyDatabase的账号执行 -
viewUserManagement是只读元数据角色,不等于开放所有权限 - 生产环境严禁长期赋予此角色
跨数据库只读需求怎么处理
一个用户要读多个库?不能靠单个 read 角色搞定。MongoDB 不支持通配符数据库名(如 "db": "*"),必须为每个库单独授权。
例如让 reporter 同时读 myapp 和 analytics:
use myapp
db.grantRolesToUser("reporter", [{ role: "read", db: "myapp" }])
use analytics
db.grantRolesToUser("reporter", [{ role: "read", db: "analytics" }])
- 两次
grantRolesToUser必须分别在对应数据库上下文中执行 - 不能用
db.adminCommand()批量操作,它不接受多库roles数组 - 如果库数量多,建议写 shell 脚本循环调用,避免手误漏库
连接时验证只读权限是否生效
创建后立刻测试,别等上线才发现权限不足。用新用户连接,尝试典型只读/写操作:
mongo --host rs1.example.com:27017 -u reporter -p s3cureP@ss --authenticationDatabase myapp
然后执行:
-
db.orders.find().limit(1)→ 应成功 -
db.orders.insertOne({ x: 1 })→ 报错:not authorized on myapp to execute command { insert: "orders", ... } -
show collections→ 成功(read包含listCollections) -
db.orders.drop()→ 报错(drop需readWrite或更高)
注意:MongoDB Shell 的 show 命令底层调用的是带权限检查的命令,不是直连文件系统,所以结果可信。如果应用层仍报错,大概率是驱动连接字符串里 authSource 指错了数据库。











