3. 启用访问控制
MongoDB 默认安装后并不启用访问控制,任何能连到 27017 端口的客户端都可以直接读写数据库,这在生产环境中是不可接受的。启用访问控制包含三件必须按顺序完成的事:先创建管理员用户,再以认证模式重启实例,最后验证未认证连接被拒绝、认证连接可正常操作。顺序不能颠倒——如果先开启认证再创建用户,本地登录也会被拒绝,只能借助 localhost exception 补救。
一、理解 localhost exception 与创建用户的时机
MongoDB 提供了一条特殊规则:当实例启用了访问控制但还没有任何用户时,允许从本机(localhost)建立一条不受认证限制的连接,用于创建第一个用户。这条连接只能创建用户,不能执行其他数据操作,且一旦第一个用户创建成功,该例外立即失效。因此正确的做法是:先在未启用认证的状态下创建管理员,或者启用认证后利用 localhost exception 创建管理员。前者更直观,推荐初学者采用。
二、创建首个管理员用户
管理员用户应创建在 admin 数据库中,并授予 userAdminAnyDatabase 与 readWriteAnyDatabase(或更严格的 root)角色。userAdminAnyDatabase 负责管理用户与角色,readWriteAnyDatabase 负责跨库读写,二者组合足以完成日常运维。以下示例在未启用认证的实例上执行:
use admin
db.createUser({
user: "adminUser",
pwd: "Str0ng_P@ssw0rd!",
roles: [
{ role: "userAdminAnyDatabase", db: "admin" },
{ role: "readWriteAnyDatabase", db: "admin" }
]
})
执行成功会返回 { ok: 1 }。此时用户已写入 admin.system.users 集合,但实例仍未要求认证,任何人都还能匿名连接。密码应满足复杂度要求,避免使用示例中的明文口令直接上线。
三、通过命令行开启认证
最直接的方式是在启动 mongod 时加上 --auth 参数。若实例正在运行,先正常关闭,再以认证模式启动:
mongod --dbpath /var/lib/mongodb --auth --port 27017 --bind_ip 127.0.0.1
启动后,未携带凭据的连接虽然能建立,但执行 show dbs、db.stats() 等命令会返回 Unauthorized 错误。这正是认证生效的直接信号。
四、通过配置文件开启认证
生产环境更推荐使用配置文件,便于集中管理端口、路径、日志与安全选项。编辑 /etc/mongod.conf:
storage:
dbPath: /var/lib/mongodb
net:
port: 27017
bindIp: 127.0.0.1
security:
authorization: enabled
关键字段是 security.authorization,取值 enabled 表示开启访问控制,disabled 表示关闭。修改后重启服务:
sudo systemctl restart mongod
命令行 --auth 与配置文件 authorization: enabled 等价,二者只需其一。若同时存在,以配置文件为准。使用配置文件的好处是重启后参数不会丢失,且可与副本集、TLS 等选项统一维护。
五、验证认证是否真正生效
验证要覆盖“拒绝”和“放行”两个方向,缺一不可。第一步,不认证直接连接并尝试操作:
mongosh --port 27017
> show dbs
MongoServerError: command listDatabases requires authentication
出现该错误说明匿名访问已被拦截。第二步,携带凭据登录并执行同样的命令:
mongosh --port 27017 -u adminUser -p 'Str0ng_P@ssw0rd!' --authenticationDatabase admin
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
能正常列出数据库,说明认证链路完整可用。也可以在已连接的会话中手动认证:
> use admin
> db.auth("adminUser", "Str0ng_P@ssw0rd!")
{ ok: 1 }
返回 { ok: 1 } 表示认证成功,返回 { ok: 0 } 则说明用户名、密码或认证库不匹配。注意 --authenticationDatabase 必须指向创建用户时所在的库,本例为 admin,否则会认证失败。
db.runCommand({connectionStatus: 1}) 的输出,其中 authenticatedUsers 会列出当前已认证用户,ok: 1 表示会话处于已认证状态,这是比单条命令更可靠的判断依据。六、常见问题与排查
- 开启认证后无法登录:确认用户创建在
admin库,且登录时指定了--authenticationDatabase admin。 - 忘记管理员密码:可临时以
--noauth启动,重置密码后再恢复认证模式,操作期间应限制网络访问。 - 配置文件不生效:检查 YAML 缩进是否为两个空格,
security与net是否同级,重启后查看日志中是否加载了该配置。 - localhost exception 失效:只要已存在任意用户,该例外就不再可用,必须使用已有凭据登录。