2. MongoDB认证机制详解

MongoDB 的认证机制解决的是“谁在连接数据库”这一问题。它并不等同于授权:认证确认身份,授权决定这个身份能对哪些库、哪些集合执行哪些操作。MongoDB 支持多种认证方式,常见的有 SCRAM、x.509 证书、LDAP 和 Kerberos。它们分别适用于不同的部署形态和安全边界,理解其原理与配置差异,是设计数据库访问安全体系的基础。

一、认证机制的基本分类

从认证凭据的存放位置和验证主体来看,MongoDB 的认证方式可以分为两类:

  • 内部认证:用户凭据存放在 MongoDB 自身的 admin 或其他数据库中,由 MongoDB 进程直接校验。典型代表是 SCRAM。
  • 外部认证:用户身份由外部系统(如企业目录、证书颁发机构、Kerberos KDC)维护,MongoDB 只负责将外部身份映射为数据库用户。典型代表是 LDAP、Kerberos 和 x.509。

这种分类决定了运维复杂度和集成方式:内部认证自包含、部署简单;外部认证需要与既有身份基础设施对接,但能实现统一账号管理和集中吊销。

二、SCRAM:默认的挑战—响应认证

SCRAM(Salted Challenge Response Authentication Mechanism)是 MongoDB 3.0 之后默认的认证机制,当前主要使用 SCRAM-SHA-1 和 SCRAM-SHA-256。它的核心特点是:密码不会以明文形式在网络中传输,也不会以明文形式存储在数据库中。

SCRAM 的认证过程可以概括为:客户端先发送用户名,服务端返回随机盐和迭代次数;客户端用盐和密码计算出 Stored Key 与 Server Key,再通过多轮挑战—响应证明自己持有密码,而不直接发送密码。服务端同样用存储的凭据参与校验。因此,即使网络被监听,攻击者也无法直接还原密码。

创建 SCRAM 用户的典型命令如下:

use admin
db.createUser({
  user: "appUser",
  pwd: passwordPrompt(),
  roles: [
    { role: "readWrite", db: "orders" },
    { role: "read", db: "reporting" }
  ],
  mechanisms: ["SCRAM-SHA-256"]
})

连接时指定认证数据库和机制:

mongosh "mongodb://appUser@10.0.0.21:27017/orders?authSource=admin&authMechanism=SCRAM-SHA-256"

SCRAM 的优点是部署简单、无需额外基础设施、支持密码轮换;缺点是账号分散在各 MongoDB 实例中,大规模环境下难以统一管理,且无法直接复用企业已有的单点登录体系。

三、x.509 证书认证

x.509 认证使用 TLS 客户端证书完成身份验证。客户端在建立 TLS 连接时出示证书,MongoDB 校验证书是否由受信任的 CA 签发、是否在有效期内、是否被吊销,然后从证书的 Subject 中提取用户名,与 MongoDB 用户进行匹配。

使用 x.509 的前提是集群已启用 TLS。服务端需要配置 CA 文件、服务端证书和私钥;客户端需要持有由同一 CA 签发的客户端证书。MongoDB 用户需要在 $external 数据库中创建,其名称必须与证书 Subject 中的可分辨名称一致。

db.getSiblingDB("$external").runCommand({
  createUser: "CN=appClient,OU=services,O=example",
  roles: [
    { role: "readWrite", db: "orders" }
  ]
})

连接时使用 authMechanism=MONGODB-X509,并指定客户端证书和私钥:

mongosh "mongodb://host:27017/orders?authMechanism=MONGODB-X509&authSource=$external" \
  --tls --tlsCertificateKeyFile client.pem --tlsCAFile ca.pem

x.509 的优势在于证书本身即凭据,适合服务间通信、自动化任务和免密码场景;证书有效期和吊销列表提供了较强的生命周期控制。缺点是证书签发、轮换和吊销流程需要 PKI 支撑,运维门槛较高。

四、LDAP 与 Kerberos:企业级外部认证

LDAP 认证将用户身份委托给目录服务(如 Active Directory、OpenLDAP)。MongoDB 支持两种模式:直接绑定由 MongoDB 将客户端提供的用户名和密码转发给 LDAP 服务器校验;代理认证则由应用先向 LDAP 认证,再以某个 MongoDB 用户身份代理操作。LDAP 用户同样创建在 $external 库中,角色仍由 MongoDB 管理。

db.getSiblingDB("$external").runCommand({
  createUser: "uid=zhangsan,ou=people,dc=example,dc=com",
  roles: [{ role: "readWrite", db: "orders" }]
})

Kerberos 认证则依赖 KDC 和票据体系。用户先通过 kinit 获取 TGT,再向 MongoDB 请求服务票据,MongoDB 校验票据中的主体名并映射为数据库用户。Kerberos 适合已有 AD 域环境、需要单点登录和强身份保证的企业场景,但配置涉及 realm、keytab、SPN 等多个环节,复杂度最高。

五、选型对比与配置要点

选择认证方式时,应重点考虑现有身份基础设施、部署规模、客户端类型和运维能力。下表给出常见维度的对比:

机制 凭据形式 用户存放位置 典型场景 主要代价
SCRAM 用户名 + 密码 MongoDB 内部库 中小规模、自建集群 账号分散,难统一吊销
x.509 TLS 客户端证书 $external 服务间通信、免密自动化 依赖 PKI,证书管理复杂
LDAP 目录账号密码 $external + 目录服务 已有 AD/LDAP 的企业 需维护目录映射与网络连通
Kerberos Kerberos 票据 $external + KDC 域环境、单点登录 配置链路长,排障门槛高

实际部署中,MongoDB 允许同时启用多种机制。例如副本集内部节点之间可使用 x.509 或 keyfile 做内部认证,而客户端使用 SCRAM 或 LDAP。需要特别注意的是,authenticationMechanisms 参数用于限制服务端接受的机制集合,authSource 决定去哪个库校验用户,二者配置不一致是认证失败最常见的原因之一。

排查认证失败时,优先确认三件事:用户是否创建在正确的认证库;连接字符串中的 authSource 是否与该库一致;服务端 authenticationMechanisms 是否包含客户端使用的机制。对于 x.509 和 Kerberos,还要检查证书有效期、Subject 匹配和票据是否过期。
MongoDB 四类认证机制:凭据来源与校验路径 客户端 / 应用 用户名 + 密码 SCRAM / LDAP TLS 客户端证书 x.509 Kerberos 票据 TGT / 服务票据 目录账号密码 LDAP 直接绑定 MongoDB 认证层 SCRAM 挑战—响应 校验本地 Stored Key TLS 证书校验 CA / 有效期 / Subject Kerberos 票据校验 SPN / keytab LDAP 绑定转发 或代理认证 凭据存储 / 外部身份源 admin 库 system.users SCRAM 凭据(盐 + 迭代 + Key) $external 库用户映射 证书 Subject → 数据库用户 KDC 与 keytab realm / SPN / 票据有效期 LDAP / Active Directory DN 绑定校验 关键参数: authSource 决定校验库; authenticationMechanisms 限制服务端接受的机制; $external 存放外部认证用户。

综合来看,SCRAM 适合快速落地和中小规模自建环境;x.509 适合服务间免密通信和需要强证书生命周期的场景;LDAP 适合已有目录服务、希望统一账号管理的企业;Kerberos 适合域环境下的单点登录和强身份保证。选型时不必追求单一机制,而应根据客户端类型、网络边界和运维能力组合使用,并通过 authSource 与 authenticationMechanisms 精确控制认证入口。