第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