文章目录
-
- 一、MongoDB认证机制概述
-
- [1.1 为什么需要认证](#1.1 为什么需要认证)
- [1.2 MongoDB认证机制对比](#1.2 MongoDB认证机制对比)
- [1.3 认证流程概览](#1.3 认证流程概览)
- 二、SCRAM-SHA认证详解
-
- [2.1 SCRAM-SHA工作原理](#2.1 SCRAM-SHA工作原理)
- [2.2 SCRAM-SHA-1 vs SCRAM-SHA-256](#2.2 SCRAM-SHA-1 vs SCRAM-SHA-256)
- [2.3 SCRAM-SHA认证配置](#2.3 SCRAM-SHA认证配置)
-
- [2.3.1 基础配置](#2.3.1 基础配置)
- [2.3.2 创建认证用户](#2.3.2 创建认证用户)
- [2.3.3 密码策略增强](#2.3.3 密码策略增强)
- [2.4 客户端连接配置](#2.4 客户端连接配置)
-
- [2.4.1 MongoDB Shell连接](#2.4.1 MongoDB Shell连接)
- [2.4.2 驱动连接配置(Node.js示例)](#2.4.2 驱动连接配置(Node.js示例))
- [2.5 SCRAM-SHA最佳实践](#2.5 SCRAM-SHA最佳实践)
- 三、X.509证书认证详解
-
- [3.1 X.509认证原理](#3.1 X.509认证原理)
- [3.2 证书准备与生成](#3.2 证书准备与生成)
-
- [3.2.1 创建CA证书](#3.2.1 创建CA证书)
- [3.2.2 创建服务器证书](#3.2.2 创建服务器证书)
- [3.2.3 创建客户端证书](#3.2.3 创建客户端证书)
- [3.3 MongoDB X.509配置](#3.3 MongoDB X.509配置)
-
- [3.3.1 服务器端配置](#3.3.1 服务器端配置)
- [3.3.2 创建X.509认证用户](#3.3.2 创建X.509认证用户)
- [3.4 客户端连接配置](#3.4 客户端连接配置)
-
- [3.4.1 MongoDB Shell连接](#3.4.1 MongoDB Shell连接)
- [3.4.2 驱动连接配置(Node.js示例)](#3.4.2 驱动连接配置(Node.js示例))
- [3.5 X.509最佳实践](#3.5 X.509最佳实践)
- 四、混合认证配置
-
- [4.1 为什么需要混合认证](#4.1 为什么需要混合认证)
- [4.2 混合认证配置](#4.2 混合认证配置)
- [4.3 用户认证方式指定](#4.3 用户认证方式指定)
- [4.4 混合认证连接示例](#4.4 混合认证连接示例)
- 五、认证机制安全最佳实践
-
- [5.1 密码安全最佳实践](#5.1 密码安全最佳实践)
- [5.2 TLS/SSL配置最佳实践](#5.2 TLS/SSL配置最佳实践)
-
- [5.2.1 安全的TLS配置](#5.2.1 安全的TLS配置)
- [5.2.2 TLS版本与加密套件](#5.2.2 TLS版本与加密套件)
- [5.3 认证流程安全加固](#5.3 认证流程安全加固)
-
- [5.3.1 失败登录限制](#5.3.1 失败登录限制)
- [5.3.2 审计日志配置](#5.3.2 审计日志配置)
- 六、常见问题与故障排除
-
- [6.1 SCRAM-SHA认证问题](#6.1 SCRAM-SHA认证问题)
-
- [6.1.1 认证失败常见原因](#6.1.1 认证失败常见原因)
- [6.1.2 密码迁移策略](#6.1.2 密码迁移策略)
- [6.2 X.509认证问题](#6.2 X.509认证问题)
-
- [6.2.1 证书验证失败](#6.2.1 证书验证失败)
- [6.2.2 证书调试技巧](#6.2.2 证书调试技巧)
- [6.3 通用认证问题](#6.3 通用认证问题)
-
- [6.3.1 认证机制协商失败](#6.3.1 认证机制协商失败)
- [6.3.2 连接字符串格式问题](#6.3.2 连接字符串格式问题)
- 七、认证机制的监控与维护
-
- [7.1 认证活动监控](#7.1 认证活动监控)
-
- [7.1.1 内置监控命令](#7.1.1 内置监控命令)
- [7.1.2 Prometheus监控指标](#7.1.2 Prometheus监控指标)
- [7.2 定期维护任务](#7.2 定期维护任务)
-
- [7.2.1 自动化密码轮换脚本](#7.2.1 自动化密码轮换脚本)
- 八、结论与建议
-
- [8.1 认证机制选择指南](#8.1 认证机制选择指南)
- [8.2 实施路线图](#8.2 实施路线图)
- [8.3 关键建议](#8.3 关键建议)
- 附录:常用认证命令速查
一、MongoDB认证机制概述
1.1 为什么需要认证
MongoDB默认配置不启用认证,这意味着任何能够连接到MongoDB服务的客户端都可以访问和修改数据。这在生产环境中是非常危险的,尤其是当MongoDB实例暴露在公共网络时。
统计数据 :根据Shodan扫描数据,2023年仍有超过15,000个MongoDB实例因未启用认证而暴露在互联网上,导致大规模数据泄露事件。
1.2 MongoDB认证机制对比
| 机制 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| SCRAM-SHA | 简单易用,无需PKI基础设施 | 依赖密码管理 | 大多数应用环境 |
| X.509 | 无密码管理,支持双向TLS | 需要PKI基础设施 | 高安全需求环境 |
| LDAP | 集中身份管理 | 依赖外部系统 | 企业级身份管理系统 |
| Kerberos | 企业级SSO支持 | 配置复杂 | 与Active Directory集成 |
1.3 认证流程概览
MongoDB认证流程:
- 客户端发起连接请求
- 服务器发送认证挑战
- 客户端响应挑战
- 服务器验证响应
- 建立安全连接(如启用TLS)
二、SCRAM-SHA认证详解
2.1 SCRAM-SHA工作原理
SCRAM(Salted Challenge Response Authentication Mechanism)是一种安全的挑战-响应式认证协议,MongoDB支持:
- SCRAM-SHA-1:基于SHA-1哈希算法
- SCRAM-SHA-256:基于SHA-256哈希算法(推荐)
认证流程:
- 服务器发送随机salt和迭代次数
- 客户端使用密码、salt和迭代次数生成哈希
- 服务器验证客户端提供的哈希
优势:防止密码在传输中被截获,抵抗重放攻击。
2.2 SCRAM-SHA-1 vs SCRAM-SHA-256
| 特性 | SCRAM-SHA-1 | SCRAM-SHA-256 |
|---|---|---|
| 安全性 | 中 | 高 |
| 算法 | SHA-1 | SHA-256 |
| 密码长度 | 无限制 | 无限制 |
| 兼容性 | 广泛 | MongoDB 4.0+ |
| 推荐程度 | 不推荐 | 强烈推荐 |
安全建议 :SCRAM-SHA-1已存在安全漏洞,仅在无法升级的旧系统中使用。对于所有新部署,应使用SCRAM-SHA-256。
2.3 SCRAM-SHA认证配置
2.3.1 基础配置
yaml
# mongod.conf
security:
authorization: enabled
keyFile: /etc/mongodb/keyfile # 仅用于副本集/分片集群
2.3.2 创建认证用户
javascript
// 创建管理员用户
use admin
db.createUser({
user: "admin",
pwd: "StrongPassword123!",
roles: [
{ role: "root", db: "admin" }
]
})
// 创建应用用户
use mydb
db.createUser({
user: "app_user",
pwd: "SecureAppPassword456!",
roles: [
{ role: "readWrite", db: "mydb" }
]
})
2.3.3 密码策略增强
javascript
// 设置密码策略(MongoDB 5.0+)
use admin
db.createRole({
role: "password_strong",
privileges: [],
roles: [],
authenticationRestrictions: [
{
passwordPolicy: {
minLength: 12,
maxLength: 128,
minUpperCase: 1,
minLowerCase: 1,
minNumeric: 1,
minSpecialChar: 1,
complexityCheck: true
}
}
]
})
// 应用密码策略
db.updateUser("app_user", {
roles: [
{ role: "readWrite", db: "mydb" },
{ role: "password_strong", db: "admin" }
]
})
2.4 客户端连接配置
2.4.1 MongoDB Shell连接
bash
# 使用SCRAM-SHA-256
mongo --username app_user --password "SecureAppPassword456!" \
--authenticationDatabase mydb \
--authenticationMechanism SCRAM-SHA-256 \
localhost:27017/mydb
2.4.2 驱动连接配置(Node.js示例)
javascript
const { MongoClient } = require('mongodb');
const uri = "mongodb://app_user:SecureAppPassword456!@localhost:27017/mydb?" +
"authMechanism=SCRAM-SHA-256&authSource=mydb";
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true
});
async function connect() {
try {
await client.connect();
console.log("Connected to MongoDB");
// 使用数据库...
} catch (err) {
console.error("Connection error:", err);
}
}
connect();
2.5 SCRAM-SHA最佳实践
-
强制使用SCRAM-SHA-256:
yaml# mongod.conf setParameter: authenticationMechanisms: "SCRAM-SHA-256" -
密码轮换策略:
javascript// 每90天轮换密码 function rotatePassword(user) { const newPassword = generateStrongPassword(); db.changeUserPassword(user, newPassword); logPasswordRotation(user); } -
密码存储安全:
- 使用密码管理器存储凭证
- 避免在代码中硬编码密码
- 使用环境变量或密钥管理系统
三、X.509证书认证详解
3.1 X.509认证原理
X.509认证基于公钥基础设施(PKI),使用TLS/SSL证书进行双向认证:
- 服务器提供证书证明身份
- 客户端也提供证书进行认证
- 服务器验证客户端证书的有效性
核心优势:无需管理密码,适合机器对机器通信和高安全性要求的环境。
3.2 证书准备与生成
3.2.1 创建CA证书
bash
# 创建CA私钥
openssl genrsa -out ca.key 4096
# 创建CA证书
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \
-out ca.crt -subj "/C=US/ST=California/L=San Francisco/O=MyOrg/OU=IT/CN=MyOrg CA"
3.2.2 创建服务器证书
bash
# 生成服务器私钥
openssl genrsa -out server.key 2048
# 创建证书签名请求(CSR)
openssl req -new -key server.key -out server.csr \
-subj "/C=US/ST=California/L=San Francisco/O=MyOrg/OU=IT/CN=mongodb.example.com"
# 签发服务器证书
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt -days 365 -sha256
3.2.3 创建客户端证书
bash
# 生成客户端私钥
openssl genrsa -out client.key 2048
# 创建CSR
openssl req -new -key client.key -out client.csr \
-subj "/C=US/ST=California/L=San Francisco/O=MyOrg/OU=IT/CN=client-app"
# 签发客户端证书
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out client.crt -days 365 -sha256
# 创建PEM文件(私钥+证书)
cat client.key client.crt > client.pem
3.3 MongoDB X.509配置
3.3.1 服务器端配置
yaml
# mongod.conf
net:
ssl:
mode: requireTLS
PEMKeyFile: /etc/mongodb/server.pem
CAFile: /etc/mongodb/ca.crt
allowInvalidCertificates: false
allowInvalidHostnames: false
security:
authorization: enabled
clusterAuthMode: x509
sslClientCertificateField: "subject_CN"
sslAllowConnectionsWithoutCertificates: false
3.3.2 创建X.509认证用户
javascript
// 创建基于证书的用户
use $external
db.getSiblingDB("$external").createUser({
user: "C=US,ST=California,L=San Francisco,O=MyOrg,OU=IT,CN=client-app",
roles: [
{ role: "readWrite", db: "mydb" }
]
})
注意:用户名必须与证书中的主题DN完全匹配。
3.4 客户端连接配置
3.4.1 MongoDB Shell连接
bash
mongo --ssl \
--sslCAFile /etc/mongodb/ca.crt \
--sslPEMKeyFile /etc/mongodb/client.pem \
--authenticationDatabase '$external' \
--authenticationMechanism MONGODB-X509 \
localhost:27017/mydb
3.4.2 驱动连接配置(Node.js示例)
javascript
const { MongoClient } = require('mongodb');
const uri = "mongodb://localhost:27017/mydb?" +
"authMechanism=MONGODB-X509&authSource=$external";
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
ssl: true,
sslValidate: true,
sslCA: fs.readFileSync('/etc/mongodb/ca.crt'),
sslCert: fs.readFileSync('/etc/mongodb/client.pem')
});
async function connect() {
try {
await client.connect();
console.log("Connected via X.509");
// 使用数据库...
} catch (err) {
console.error("Connection error:", err);
}
}
connect();
3.5 X.509最佳实践
-
证书生命周期管理:
bash# 检查证书有效期 openssl x509 -in client.crt -noout -dates -
证书吊销机制:
- 设置CRL(证书吊销列表)
- 定期更新CRL
-
多租户支持:
javascript// 为不同租户创建不同OU的证书 use $external db.createUser({ user: "C=US,ST=California,L=San Francisco,O=MyOrg,OU=tenant1,CN=app", roles: [{ role: "readWrite", db: "tenant1" }] }) -
证书自动续期:
bash# 使用cron定期检查并续期证书 0 0 * * 0 /usr/local/bin/renew-mongodb-cert.sh
四、混合认证配置
4.1 为什么需要混合认证
在某些场景下,可能需要同时支持多种认证机制:
- 旧系统与新系统并存
- 不同客户端类型(人类用户vs服务账户)
- 逐步迁移认证机制
4.2 混合认证配置
yaml
# mongod.conf
setParameter:
authenticationMechanisms: "SCRAM-SHA-256,MONGODB-X509"
4.3 用户认证方式指定
javascript
// 创建支持两种认证方式的用户
use admin
db.createUser({
user: "hybrid_user",
pwd: "Password123!",
roles: ["readWriteAnyDatabase"],
mechanisms: ["SCRAM-SHA-256"]
})
// 创建X.509用户
use $external
db.createUser({
user: "C=US,ST=California,L=San Francisco,O=MyOrg,OU=IT,CN=client-app",
roles: ["readWrite"],
mechanisms: ["MONGODB-X509"]
})
4.4 混合认证连接示例
javascript
// 服务账户使用X.509
const serviceClient = new MongoClient(
"mongodb://localhost:27017/mydb?" +
"authMechanism=MONGODB-X509&authSource=$external",
{ /* SSL配置 */ }
);
// 管理员使用SCRAM-SHA-256
const adminClient = new MongoClient(
"mongodb://admin:Password123!@localhost:27017/admin?" +
"authMechanism=SCRAM-SHA-256",
{ useNewUrlParser: true }
);
五、认证机制安全最佳实践
5.1 密码安全最佳实践
-
密码复杂度要求:
javascript// MongoDB 5.0+密码策略 db.createRole({ role: "strong_password", authenticationRestrictions: [{ passwordPolicy: { minLength: 12, minUpperCase: 1, minLowerCase: 1, minNumeric: 1, minSpecialChar: 1 } }] }); -
密码轮换机制:
javascript// 每90天检查密码年龄 function checkPasswordAge(user) { const userInfo = db.getUser(user); const lastChanged = userInfo.credentials.SCRAM.sha256.lastChanged; const daysSinceChange = (Date.now() - lastChanged.getTime()) / (1000 * 60 * 60 * 24); if (daysSinceChange > 90) { alertUserToChangePassword(user); return false; } return true; } -
密码存储安全:
- 使用密码管理器
- 避免在代码中硬编码
- 使用密钥管理系统(如HashiCorp Vault)
5.2 TLS/SSL配置最佳实践
5.2.1 安全的TLS配置
yaml
# mongod.conf
net:
ssl:
mode: requireTLS
PEMKeyFile: /etc/mongodb/server.pem
CAFile: /etc/mongodb/ca.crt
disabledProtocols: "TLS1_0,TLS1_1" # 仅允许TLS 1.2+
weakCertificateValidation: false
allowInvalidHostnames: false
5.2.2 TLS版本与加密套件
bash
# 仅允许强加密套件
openssl ciphers -v 'HIGH:!aNULL:!MD5:!3DES' | grep TLSv1.2
# 配置MongoDB(通过操作系统配置)
# Ubuntu/Debian: /etc/ssl/openssl.cnf
# RHEL/CentOS: /etc/pki/tls/openssl.cnf
5.3 认证流程安全加固
5.3.1 失败登录限制
javascript
// MongoDB 5.0+登录失败限制
use admin
db.createRole({
role: "login_rate_limiter",
privileges: [],
authenticationRestrictions: [
{
maxFailureAttempts: 5,
lockoutDurationSeconds: 900
}
]
})
// 应用到用户
db.updateUser("app_user", {
roles: [
{ role: "readWrite", db: "mydb" },
{ role: "login_rate_limiter", db: "admin" }
]
})
5.3.2 审计日志配置
yaml
# mongod.conf
auditLog:
destination: file
format: JSON
path: /var/log/mongodb/audit.log
filter: '{ "auditType": { "$in": ["authCheck", "login"] } }'
六、常见问题与故障排除
6.1 SCRAM-SHA认证问题
6.1.1 认证失败常见原因
| 错误信息 | 原因 | 解决方案 |
|---|---|---|
Authentication failed |
密码错误 | 检查密码是否正确 |
SCRAM-SHA-1 is disabled |
未启用SCRAM-SHA-1 | 使用SCRAM-SHA-256 |
User not found |
用户不存在 | 创建用户 |
Authentication mechanism is not supported |
驱动不支持 | 升级驱动 |
6.1.2 密码迁移策略
javascript
// 从SCRAM-SHA-1迁移到SCRAM-SHA-256
function migrateToSha256(username) {
const user = db.getUser(username);
const password = promptForNewPassword();
db.updateUser(username, {
pwd: password,
mechanisms: ["SCRAM-SHA-256"]
});
}
6.2 X.509认证问题
6.2.1 证书验证失败
| 错误信息 | 原因 | 解决方案 |
|---|---|---|
SSL handshake failed |
证书链不完整 | 确保CA文件包含完整证书链 |
Invalid hostname |
CN不匹配 | 检查证书CN是否匹配主机名 |
Certificate expired |
证书过期 | 重新生成证书 |
User not found |
DN不匹配 | 确保DN与用户创建时一致 |
6.2.2 证书调试技巧
bash
# 检查证书详细信息
openssl x509 -in client.crt -text -noout
# 验证证书链
openssl verify -CAfile ca.crt client.crt
# 模拟TLS连接
openssl s_client -connect localhost:27017 -cert client.crt -key client.key -CAfile ca.crt
6.3 通用认证问题
6.3.1 认证机制协商失败
bash
# 检查服务器支持的认证机制
mongo --eval "db.serverStatus().authenticationMechanisms"
# 客户端明确指定机制
mongo --authenticationMechanism SCRAM-SHA-256 ...
6.3.2 连接字符串格式问题
错误连接字符串:
mongodb://user:pass@host:port/db?authSource=admin
正确连接字符串:
mongodb://user:pass@host:port/db?authSource=admin&authMechanism=SCRAM-SHA-256
七、认证机制的监控与维护
7.1 认证活动监控
7.1.1 内置监控命令
javascript
// 查看当前认证用户
db.runCommand({ connectionStatus: 1 })
// 查看登录历史
db.getSiblingDB("admin").system.log.find({
"log": /login/
}).sort({ timestamp: -1 }).limit(10)
7.1.2 Prometheus监控指标
yaml
# mongodb_exporter 配置
rules:
- name: Authentication
rules:
- alert: HighLoginFailureRate
expr: rate(mongodb_auth_total{result="failure"}[5m]) > 5
for: 5m
labels:
severity: warning
annotations:
summary: "High MongoDB login failure rate"
description: "{{ $value }} login failures in the last 5 minutes"
- alert: NoSuccessfulLogins
expr: rate(mongodb_auth_total{result="success"}[1h]) == 0
for: 1h
labels:
severity: critical
annotations:
summary: "No successful MongoDB logins"
description: "No successful logins in the last hour"
7.2 定期维护任务
| 任务 | 频率 | 工具 |
|---|---|---|
| 密码轮换 | 90天 | 自定义脚本 |
| 证书检查 | 30天 | OpenSSL |
| 权限审查 | 每月 | MongoDB Shell |
| 认证机制审计 | 每季度 | 自定义脚本 |
7.2.1 自动化密码轮换脚本
bash
#!/bin/bash
# rotate-mongodb-passwords.sh
USERS=("app_user" "report_user" "admin")
EXPIRATION_DAYS=90
for user in "${USERS[@]}"; do
# 检查密码年龄
age=$(mongo --eval "db.getUser('$user').credentials.SCRAM.sha256.lastChanged" | grep -o "[0-9]\+")
days_old=$(( ( $(date +%s) - age ) / 86400 ))
if [ $days_old -ge $EXPIRATION_DAYS ]; then
new_password=$(generate_strong_password)
mongo <<EOF
use admin
db.changeUserPassword('$user', '$new_password')
EOF
save_password_to_vault $user $new_password
fi
done
八、结论与建议
8.1 认证机制选择指南
| 场景 | 推荐机制 | 说明 |
|---|---|---|
| 常规应用环境 | SCRAM-SHA-256 | 简单、安全、广泛支持 |
| 高安全要求环境 | X.509 + TLS | 无密码管理,强身份验证 |
| 混合环境 | SCRAM-SHA-256 + X.509 | 逐步迁移,支持不同客户端 |
| 云环境 | SCRAM-SHA-256 + IAM | 结合云平台身份管理 |
8.2 实施路线图
-
评估阶段:
- 确定当前认证状态
- 评估安全需求和合规要求
-
规划阶段:
- 选择认证机制
- 规划迁移路径
-
实施阶段:
- 配置认证机制
- 创建用户和角色
- 更新客户端连接
-
维护阶段:
- 建立监控和告警
- 实施定期维护计划
8.3 关键建议
- 不要在生产环境中使用默认配置:始终启用认证
- 优先使用SCRAM-SHA-256:它是当前最平衡的安全选择
- X.509适合机器对机器通信:避免密码管理复杂性
- 定期审计认证配置:确保符合安全最佳实践
- 结合TLS使用:认证不应是唯一的安全层
关键提示 :认证只是安全的第一道防线。实施纵深防御策略,结合网络隔离、加密和审计,才能构建真正的安全体系。
通过实施本指南中的认证机制,您的MongoDB部署将获得强大的身份验证能力,显著降低未授权访问的风险。记住,好的安全不是一蹴而就的,而是持续改进的过程。定期审查和更新认证策略,使其适应不断变化的安全威胁,是保持系统安全的关键。
附录:常用认证命令速查
javascript
// 查看支持的认证机制
db.serverStatus().authenticationMechanisms
// 检查当前用户权限
db.runCommand({ connectionStatus: 1 })
// 修改用户密码
db.changeUserPassword("username", "newPassword")
// 查看用户详细信息
db.getUser("username", { showCredentials: true })
// 创建X.509用户
use $external
db.createUser({ ... })
// 检查证书有效性
openssl x509 -in cert.pem -noout -text