Skip to content

MongoDB 用户与角色管理

基于角色的访问控制(RBAC)

MongoDB 使用基于角色的访问控制(Role-Based Access Control,RBAC)来管理用户对数据库资源的访问权限。RBAC 模型将权限分配给角色,然后将角色分配给用户,实现了权限的集中管理和精细控制。

RBAC 核心概念

  • 用户(User):数据库的访问主体,通过用户名和密码进行认证
  • 角色(Role):一组权限的集合,定义了用户可以执行的操作
  • 权限(Privilege):定义了对特定资源的操作权限,包括资源类型和操作类型
  • 资源(Resource):数据库对象,如数据库、集合、集合集或集群
  • 操作(Action):对资源可以执行的操作,如查询、插入、更新、删除等

内置角色

MongoDB 提供了多种内置角色,涵盖了从集群管理到数据库操作的各种权限需求。内置角色可以分为以下几类:

1. 数据库用户角色

角色名称描述
read允许用户读取指定数据库中的数据
readWrite允许用户读取和写入指定数据库中的数据

2. 数据库管理角色

角色名称描述
dbAdmin允许用户执行数据库管理任务,如索引创建、统计信息查看等
dbOwner数据库所有者,拥有 readWrite、dbAdmin 和 userAdmin 权限
userAdmin允许用户管理指定数据库中的用户和角色

3. 集群管理角色

角色名称描述
clusterAdmin集群管理员,拥有 clusterManager、clusterMonitor 和 hostManager 权限
clusterManager允许用户管理集群配置,如分片、复制集等
clusterMonitor允许用户监控集群状态
hostManager允许用户管理服务器,如关闭、重启等

4. 备份恢复角色

角色名称描述
backup允许用户执行备份操作
restore允许用户执行恢复操作

5. 超级用户角色

角色名称描述
root超级用户,拥有所有权限

6. 其他角色

角色名称描述
__system内部角色,用于 MongoDB 系统进程

用户管理

1. 创建用户

bash
# 切换到 admin 数据库
use admin

# 创建管理员用户
db.createUser({
  user: "admin",
  pwd: "password",
  roles: [
    { role: "root", db: "admin" }
  ]
})

# 在指定数据库中创建用户
use mydatabase
db.createUser({
  user: "myuser",
  pwd: "mypassword",
  roles: [
    { role: "readWrite", db: "mydatabase" },
    { role: "read", db: "otherdatabase" }
  ]
})

2. 查看用户

bash
# 查看当前数据库中的用户
db.getUsers()

# 查看指定数据库中的用户
use admin
db.getUsers()

# 查看特定用户
db.getUser("admin")

3. 修改用户密码

bash
# 修改当前数据库中用户的密码
db.changeUserPassword("myuser", "newpassword")

# 使用 updateUser 修改密码
db.updateUser("myuser", { pwd: "newpassword" })

4. 修改用户角色

bash
# 修改用户角色
db.updateUser("myuser", {
  roles: [
    { role: "readWrite", db: "mydatabase" },
    { role: "dbAdmin", db: "mydatabase" }
  ]
})

5. 删除用户

bash
# 删除当前数据库中的用户
db.dropUser("myuser")

# 删除指定数据库中的用户
use admin
db.dropUser("admin")

角色管理

1. 创建自定义角色

bash
# 创建自定义角色
db.createRole({
  role: "myCustomRole",
  privileges: [
    { resource: { db: "mydatabase", collection: "mycollection" }, actions: ["find", "insert", "update"] },
    { resource: { db: "mydatabase", collection: "system.js" }, actions: ["find"] }
  ],
  roles: [
    { role: "read", db: "otherdatabase" }
  ]
})

2. 查看角色

bash
# 查看当前数据库中的所有角色
db.getRoles()

# 查看指定数据库中的角色
use admin
db.getRoles()

# 查看特定角色的详细信息
db.getRole("myCustomRole", { showPrivileges: true })

3. 修改自定义角色

bash
# 修改自定义角色
db.updateRole("myCustomRole", {
  privileges: [
    { resource: { db: "mydatabase", collection: "mycollection" }, actions: ["find", "insert", "update", "remove"] },
    { resource: { db: "mydatabase", collection: "system.js" }, actions: ["find"] }
  ],
  roles: [
    { role: "read", db: "otherdatabase" }
  ]
})

4. 删除自定义角色

bash
# 删除自定义角色
db.dropRole("myCustomRole")

权限管理

1. 权限资源

权限资源可以是以下类型:

  • 集群(Cluster):整个 MongoDB 集群
  • 数据库(Database):指定数据库
  • 集合(Collection):指定数据库中的指定集合
  • 集合集(Collection Set):指定数据库中的多个集合
  • 任意资源(Any Resource):所有资源

2. 权限操作

权限操作包括:

  • 查询操作find, aggregate, distinct
  • 写入操作insert, update, remove
  • 管理操作createIndex, dropIndex, createCollection
  • 集群操作addShard, removeShard, replSetReconfig

3. 权限示例

bash
# 授予用户对集合的所有权限
db.grantPrivilegesToRole("myRole", [
  { resource: { db: "mydb", collection: "mycoll" }, actions: ["find", "insert", "update", "remove"] }
])

# 撤销用户对集合的权限
db.revokePrivilegesFromRole("myRole", [
  { resource: { db: "mydb", collection: "mycoll" }, actions: ["remove"] }
])

认证机制

1. 启用认证

要启用 MongoDB 的认证机制,需要在配置文件中设置:

yaml
security:
  authorization: enabled

或者在启动时指定 --auth 参数:

bash
mongod --auth --config /etc/mongod.conf

2. 用户认证

bash
# 使用 mongo 客户端认证
mongo -u admin -p password --authenticationDatabase admin

# 在 mongo shell 中认证
use admin
db.auth("admin", "password")

# 使用连接字符串认证
mongo "mongodb://admin:password@localhost:27017/admin"

3. 复制集认证

对于复制集,需要配置密钥文件或证书认证:

yaml
security:
  clusterAuthMode: keyFile
  keyFile: /etc/mongodb/keyfile

最佳实践

1. 最小权限原则

  • 为用户分配最小必要的权限
  • 避免使用 rootdbOwner 等高级角色,除非必要
  • 为不同的用户分配不同的角色,根据其工作职责

2. 管理员用户管理

  • 创建专门的管理员用户,用于管理其他用户和角色
  • 不要将管理员用户用于普通应用访问
  • 定期轮换管理员密码
  • 限制管理员用户的访问IP

3. 应用用户管理

  • 为每个应用创建独立的用户
  • 根据应用需求分配适当的角色
  • 定期轮换应用用户密码
  • 使用环境变量或密钥管理系统存储密码

4. 角色设计

  • 合理设计自定义角色,避免权限过大
  • 定期审查角色权限,确保符合业务需求
  • 使用角色继承,减少重复配置

5. 审计与监控

  • 启用审计日志,记录用户的认证和授权操作
  • 监控用户活动,检测异常行为
  • 定期审查用户列表,清理不再使用的用户

6. 密码策略

  • 使用强密码,包含大小写字母、数字和特殊字符
  • 定期轮换密码
  • 避免在代码中硬编码密码
  • 使用 TLS/SSL 加密传输密码

常见问题与解决方案

问题:忘记管理员密码

解决方案

  1. 关闭 MongoDB 服务
  2. 以无认证模式启动 MongoDB:
    bash
    mongod --noauth --config /etc/mongod.conf
  3. 连接到 MongoDB 并重置管理员密码:
    bash
    mongo
    use admin
    db.changeUserPassword("admin", "newpassword")
  4. 关闭 MongoDB 服务,重新以认证模式启动

问题:用户无法访问指定数据库

解决方案

  1. 检查用户是否具有访问该数据库的角色
  2. 检查用户认证时使用的数据库是否正确
  3. 检查角色的权限是否包含对该数据库的操作
  4. 使用 db.getUser() 查看用户的详细信息和角色

问题:自定义角色权限不生效

解决方案

  1. 检查角色的权限资源是否正确
  2. 检查角色的操作是否包含所需的操作
  3. 检查用户是否已被正确分配该角色
  4. 使用 db.getRole() 查看角色的详细权限

问题:复制集认证失败

解决方案

  1. 检查密钥文件是否存在,权限是否为 600
  2. 检查所有复制集成员使用的密钥文件是否相同
  3. 检查 clusterAuthMode 配置是否正确
  4. 查看 MongoDB 日志,获取详细的错误信息

常见问题(FAQ)

Q1: MongoDB 中的 read 角色和 readWrite 角色有什么区别?

A1: read 角色允许用户读取指定数据库中的数据,包括执行 findaggregate 等查询操作;readWrite 角色在 read 角色的基础上,还允许用户执行写入操作,如 insertupdateremove 等。

Q2: 如何限制用户只能访问特定集合?

A2: 可以通过创建自定义角色,指定资源为特定集合,并授予相应的操作权限。例如:

bash
db.createRole({
  role: "myCollectionRole",
  privileges: [
    { resource: { db: "mydb", collection: "mycoll" }, actions: ["find"] }
  ],
  roles: []
})

Q3: MongoDB 支持基于 IP 的访问控制吗?

A3: MongoDB 本身不直接支持基于 IP 的访问控制,但可以通过配置操作系统防火墙或使用 MongoDB Atlas 等托管服务来实现。例如,使用 iptables 限制 MongoDB 端口的访问 IP。

Q4: 如何查看用户的详细权限?

A4: 可以使用 db.getUser() 命令查看用户的详细信息,包括角色和权限:

bash
db.getUser("myuser", { showPrivileges: true, showCredentials: true })

Q5: 如何在应用中安全地存储 MongoDB 密码?

A5: 推荐使用环境变量、密钥管理系统(如 AWS KMS、HashiCorp Vault)或配置文件加密来存储 MongoDB 密码,避免在代码中硬编码密码。在连接 MongoDB 时,从这些安全存储中获取密码。