跳到主要内容

第7章 MongoDB基于角色的访问控制

7.1 访问控制概述

MongoDB基于角色的访问控制(RBAC)提供了灵活的权限管理机制,通过用户、角色和权限的组合来保护数据库安全。每个用户可以被分配一个或多个角色,每个角色定义了在特定数据库上的操作权限。

核心概念

用户(User):访问数据库的身份标识,包含用户名、密码和所属角色。

角色(Role):权限的集合,定义了在特定数据库或集合上允许执行的操作。

权限(Privilege):在特定资源上执行特定操作的许可。

认证数据库:存储用户凭据的数据库,用户登录时需要指定此数据库。

📚 权限设计原则

MongoDB遵循最小权限原则:用户只应该拥有完成其工作所需的最小权限集合。

内置角色系统

MongoDB提供了一套预定义的内置角色,覆盖了常见的权限需求:

数据库级角色

角色名称权限描述适用场景
read读取数据库中所有非系统集合只读用户,数据分析
readWrite读写数据库中所有非系统集合应用程序用户
dbAdmin数据库管理操作(索引、统计等)数据库管理员
dbOwner数据库的所有权限数据库所有者
userAdmin管理数据库用户和角色用户管理员

集群级角色

角色名称权限描述适用场景
readAnyDatabase读取所有数据库全局只读监控
readWriteAnyDatabase读写所有数据库全局应用账户
userAdminAnyDatabase管理所有数据库用户超级用户管理员
dbAdminAnyDatabase管理所有数据库系统管理员
root超级用户权限系统超级管理员

启用访问控制

配置访问控制

⚠️ 重要安全配置

启用访问控制前,务必先创建管理员账户,否则将无法管理数据库。

# 编辑MongoDB配置文件
vim /opt/mongo_27017/conf/mongodb.conf

# 添加安全配置
security:
authorization: enabled

重启MongoDB服务

# 重启服务使配置生效
systemctl restart mongod

# 验证服务状态
systemctl status mongod
⚠️ 服务重启提醒

重启服务会中断所有连接,建议在维护窗口执行此操作。

管理员账户管理

创建超级管理员

在未开启访问控制时,创建第一个管理员账户:

// 切换到admin数据库
use admin

// 创建超级管理员用户
db.createUser({
user: "myUserAdmin",
pwd: "StrongPassword123!",
roles: [
{ role: "userAdminAnyDatabase", db: "admin" },
"readWriteAnyDatabase"
]
})

验证管理员账户

// 查看创建的用户信息
db.getUsers()

预期输出示例:

[
{
"_id": "admin.myUserAdmin",
"userId": UUID("bd30449e-6147-41b4-9af7-10c7f4174944"),
"user": "myUserAdmin",
"db": "admin",
"roles": [
{
"role": "userAdminAnyDatabase",
"db": "admin"
},
{
"role": "readWriteAnyDatabase",
"db": "admin"
}
],
"mechanisms": [
"SCRAM-SHA-1",
"SCRAM-SHA-256"
]
}
]

管理员登录

# 使用管理员账户登录
mongo --authenticationDatabase "admin" -u "myUserAdmin" -p
💡 安全建议
  • 管理员密码应使用强密码策略
  • 定期更换管理员密码
  • 限制管理员账户的使用场景

普通用户管理

用户管理命令

命令功能描述
db.createUser()创建新用户
db.getUsers()查看数据库用户列表
db.getUser(username)查看指定用户信息
db.updateUser()更新用户信息
db.changeUserPassword()修改用户密码
db.dropUser()删除用户
db.dropAllUsers()删除所有用户
db.grantRolesToUser()授予用户角色
db.revokeRolesFromUser()撤销用户角色
db.auth()用户身份验证

创建普通用户

// 使用管理员身份切换到test数据库
use test

// 创建具有不同权限的普通用户
db.createUser({
user: "myTester",
pwd: "TesterPass456!",
roles: [
{ role: "readWrite", db: "db1" },
{ role: "read", db: "db2" }
]
})

// 查看创建的用户
db.getUsers()

创建测试数据

// 为权限测试准备数据
use db1
db.write.insertOne({"name": "readWrite"})

use db2
db.read.insertOne({"name": "read"})

修改用户权限

// 使用管理员账户修改用户权限
use test
db.updateUser(
"myTester",
{
roles: [
{ role: "read", db: "db1" },
{ role: "readWrite", db: "db2" },
{ role: "readWrite", db: "test" }
]
}
)

// 创建测试数据
db.user.insertOne({name: "test"})

权限测试验证

普通用户登录

# 使用普通用户登录
mongo --authenticationDatabase "test" -u "myTester" -p

权限验证测试

初始权限测试
// 查看可访问的数据库
show dbs

// 测试db1权限(readWrite)
use db1
show tables
db.write.find() // 正常读取
db.write.insertOne({name: "ok"}) // 正常写入

// 测试db2权限(read)
use db2
show tables
db.read.find() // 正常读取
db.read.insertOne({name: "ok"}) // 写入失败
修改后权限测试
// 测试db1权限(read)
use db1
db.write.find() // 正常读取
db.write.insertOne({name: "ok"}) // 写入失败

// 测试db2权限(readWrite)
use db2
db.read.find() // 正常读取
db.read.insertOne({name: "ok"}) // 正常写入

// 测试test权限(readWrite)
use test
show tables
db.user.find() // 正常读取
db.user.insertOne({name: "ok"}) // 正常写入
📋 权限验证结果

通过测试可以验证:

  • 用户只能访问被授权的数据库
  • 不同角色对应不同的操作权限
  • 权限修改会立即生效

用户管理最佳实践

用户删除

// 使用管理员账户删除用户
mongo --authenticationDatabase "admin" -u "myUserAdmin" -p
use test
db.dropUser("myTester")

安全策略建议

💡 生产环境最佳实践

账户安全

  • 使用强密码策略,包含大小写字母、数字和特殊字符
  • 定期更换密码,建议3-6个月一次
  • 为不同环境(开发、测试、生产)使用不同的账户

权限管理

  • 遵循最小权限原则,只分配必要的权限
  • 定期审查用户权限,清理不再需要的账户
  • 为应用程序创建专用用户,避免使用管理员账户

监控审计

  • 启用MongoDB审计日志,记录用户操作
  • 监控异常登录行为和权限变更
  • 建立用户操作的审批流程

连接字符串格式

# 标准连接格式
mongo --authenticationDatabase "数据库名" -u "用户名" -p

# 应用程序连接字符串
mongodb://username:password@host:port/database?authSource=authDatabase

# 示例
mongodb://myTester:TesterPass456!@localhost:27017/db1?authSource=test
⚠️ 连接安全提醒
  • 避免在命令历史中保存密码
  • 使用配置文件或环境变量存储敏感信息
  • 生产环境建议启用SSL/TLS加密连接

常见问题排查

认证失败

  • 检查用户名和密码是否正确
  • 确认认证数据库(authSource)是否正确
  • 验证用户是否存在且未被删除

权限不足

  • 检查用户的角色分配
  • 确认操作的数据库是否在用户权限范围内
  • 验证角色的具体权限内容

更新: 2025-01-26