db.createUser()是MongoDB中创建用户的唯一可靠方式,必须在目标数据库上下文中执行,角色需为数组格式,密码含特殊字符须加单引号,且authSource必须与用户所在库一致。

mongo shell 里用 db.createUser() 是唯一可靠方式
驱动或 GUI 工具创建用户常失败,因为权限模型依赖数据库上下文和角色绑定逻辑,只有 mongo 或 mongosh 连上目标库后执行 db.createUser() 才能确保角色被正确解析和持久化。
常见错误现象:MongoServerError: RoleNotFoundException(角色名拼错或没指定 db)、Unauthorized(连的是 admin 库但用户建在其他库)、或用户建完却无法登录(密码用了特殊字符但没加引号)。
- 必须先
use admin再创建管理员用户;若要建某业务库的读写用户,得先use your_db_name,再调db.createUser() -
roles字段必须是数组,哪怕只给一个角色,例如[{ role: "readWrite", db: "myapp" }],不能写成{ role: "readWrite", db: "myapp" } - 密码含
$、/、@等字符时,务必用单引号包裹,比如pwd: 'pass$123',否则 shell 会误解析
“readWrite” 角色不等于对所有集合可读写
它只作用于指定 db 下的普通集合,不覆盖 system.* 集合、视图、或启用了字段级加密(FLE)的集合。更关键的是:如果集合启用了 collation 或使用了 timeseries 类型,某些写操作(如 updateMany 带复杂条件)可能仍被拒绝,除非显式授予 dbAdmin 或自定义角色。
- 对分片集群,
readWrite只在该库所在分片生效;跨库聚合($lookup)需要目标库也授对应权限 - 如果应用用
insertOne往myapp.users写,但用户角色里db写成"admin",就会报NotAuthorized - 启用
authorization: enabled后,localhost exception失效——意味着即使从本机连,也必须用账号密码,别指望跳过认证
连接字符串里必须显式指定 authSource
很多人填了用户名密码却连不上,根本原因是没告诉驱动“去哪个库查这个用户”。MongoDB 不默认在当前库找用户,而是查 authSource 指定的库(通常是 admin)。省略或写错会导致 Authentication failed。
- URI 示例:
mongodb://myuser:mypass@localhost:27017/myapp?authSource=admin—— 这里myapp是业务库,authSource=admin表示用户记录存在admin库 - 如果用户建在
myapp库本身(不推荐),则authSource必须设为myapp,否则驱动仍去admin查,找不到人 - Node.js 驱动里用
auth选项替代 URI 参数时,authSource是必填字段,漏掉直接连接失败
测试权限是否真生效,别只看能不能连上
连上不等于有权限。常见假阳性:用 mongosh -u user -p pass --authenticationDatabase admin 成功登录,但一执行 db.collection.insertOne({}) 就报错。这是因为 shell 默认进的是 test 库,而你的用户只在 myapp 库有 readWrite 权限。
- 登录后立刻
use myapp,再试db.foo.insertOne({x:1})和db.foo.find().toArray() - 故意用错库测试边界:
use admin后执行db.runCommand({listDatabases:1}),应报not authorized(除非给了root角色) - 注意
mongosh的自动补全会缓存旧权限状态,换用户后最好退出重进,或用db.logout()清上下文
最易被忽略的一点:MongoDB 的角色权限是静态绑定的,改了用户角色不会自动刷新已存在的连接会话。重启应用或断开重连才能生效。











