Atlas数据库用户权限由认证库与角色共同决定:认证库(如admin)仅用于验证身份,实际访问范围由角色绑定的db字段(如{role:"read",db:"orders"})严格限定,未显式授权的数据库默认不可见。

Atlas 数据库用户无法被限制到“指定某个数据库”——它天然就是按数据库粒度授权的,但关键在于:你创建用户时指定的 db 参数,和分配的角色作用域,共同决定了实际能访问哪些库。搞错这两点,就容易误以为“限制失败”。
创建用户时指定 db 参数决定默认认证库
Atlas 中所有数据库用户都必须关联一个「认证数据库」(authentication database),通常是 admin。这个库不是访问目标,而是存放用户凭证的地方。
- 用
db.createUser()创建用户时,db字段填的是认证库名,不是权限库名;例如db: "admin"表示把用户信息存进admin库 - 连接字符串里带的
?authSource=xxx必须和这个db一致,否则认证直接失败,连「权限检查」那步都走不到 - 如果你填了
db: "myapp",那这个用户就必须用?authSource=myapp连接,且 Atlas 会默认尝试在myapp库里查凭证——但 Atlas 不允许在非admin库里存用户(除非你手动启用了 legacy user storage,不推荐)
角色(role)才真正控制能访问哪些数据库
权限由角色定义,而角色的作用范围(resource)明确绑定到具体数据库或集群。Atlas 内置角色如 read、readWrite 都是「数据库级角色」,必须配合 db 字段使用。
-
{ role: "read", db: "orders" }→ 只能读orders库,对users库完全不可见 -
{ role: "readWriteAnyDatabase", db: "admin" }→ 这是高危权限,能读写所有库,db: "admin"在这里是占位,不代表只作用于 admin 库 - 自定义角色也必须显式声明
resource: { db: "logs", collection: "" },空字符串表示整个库;不能写成resource: { db: "" },那会被视为集群级资源,需要额外权限
连接时用 defaultAuthDb 或 authSource 不影响权限范围
很多人试图通过连接字符串里的 authSource 来“切换可访问库”,这是误解。这个参数只告诉驱动:“去哪个库查我的用户名密码”,跟授权无关。
- 错误认知:
mongodb+srv://u:p@cluster/?authSource=reports就只能访问reports库 - 真实情况:只要用户被授予了
{ role: "read", db: "analytics" },哪怕authSource=reports,照样能连analytics库并执行db.getCollectionNames() - 唯一例外是
__system或local这类系统库,任何用户默认无权访问,无论角色怎么配
真正隔离数据库访问的可靠方式
如果目标是让 A 用户完全看不到 B 数据库,仅靠角色还不够——因为 Atlas 默认允许用户列出所有数据库(listDatabases 权限由 clusterMonitor 等角色隐含提供)。要彻底隐藏:
- 不要给用户分配任何含
listDatabases的角色(比如避开dbAdminAnyDatabase、clusterAdmin) - 确认用户只拥有明确指定
db的数据库角色,例如read+db: "finance",不加其他通配角色 - 如果项目里有多个敏感库,建议拆到不同 Atlas 项目(Project)中——项目之间网络、用户、权限完全隔离,比库级控制更彻底
最容易被忽略的一点:Atlas 用户界面里看到的「数据库用户列表」是项目级的,但每个用户的权限只在其被显式授予权限的那些库上生效;没被列在角色里的库,不是“限制访问”,而是“压根不存在访问入口”。











