x.509认证失败主因是证书subject未在$external库中创建对应用户:需用openssl提取完整subject,再通过db.getSiblingDB("$external").createUser()注册,且连接时必须指定authMechanism="MONGODB-X509"和authSource="$external"。

能连上但报 not authorized on $external to execute command,说明 TLS 握手和证书校验都过了,问题出在 MongoDB 没把证书里的身份映射成有效用户——这是 x.509 免密登录最常卡住的地方。
客户端证书 subject 必须显式添加为 $external 用户
MongoDB 不会自动把证书 CN 或 DN 当成用户。你得手动用 db.createUser() 把证书 subject 字符串注册进 $external 数据库。
- 先用 OpenSSL 提取 subject(注意保留引号和空格):
openssl x509 -in client.pem -subject -noout | sed 's/subject= //' - 连接到 mongod(需有 root 权限),执行:
db.getSiblingDB("$external").createUser({ user: "CN=client1,OU=dev,O=myorg", roles: [{ role: "readWrite", db: "myapp" }], mechanisms: ["MONGODB-X509"] }) - user 字段值必须和证书实际 subject 完全一致,包括大小写、空格、逗号顺序
连接时 authMechanism 和 authSource 缺一不可
Node.js 驱动里漏掉 authSource 是高频错误。只设 authMechanism: "MONGODB-X509" 不够,MongoDB 默认去 admin 库查用户,而 x.509 用户只存在于 $external。
- 完整连接选项必须包含:
{ tls: { ca: [fs.readFileSync('ca.pem')], cert: fs.readFileSync('client.pem'), key: fs.readFileSync('client.key') }, authMechanism: "MONGODB-X509", authSource: "$external" } - URL 形式也一样:
mongodb://localhost:27017/?authMechanism=MONGODB-X509&authSource=$external - 如果用 Compass 连接,记得在 Authentication 页签里选
MONGODB-X509,并勾选Use X.509 Certificate
证书字段不满足要求会导致静默拒绝
mongod 不会明确告诉你“keyUsage 错了”,而是直接拒绝认证,日志里可能只有模糊的 TLS 握手失败或空 auth 错误。
- 客户端证书必须含:
keyUsage = digitalSignature和extendedKeyUsage = clientAuth - 不能和集群成员证书共用同一组
O/OU/DC—— 否则 mongod 会当成集群内通信,跳过用户校验 - 证书未过期,且服务器系统时间不能比证书有效期早超过 30 天(否则启动时就警告)
- 私钥如果是 PKCS#8 格式,必须用 PBES2 加密;其他加密方式(如 PBKDF2)会被 mongod 拒绝
最容易被忽略的是 subject 字符串的精确匹配:哪怕多一个空格、少一个换行、OU 大小写不一致,db.createUser() 创建的用户就对不上证书,整个流程就卡在“已连接但无权限”。建议把 openssl x509 -text -in client.pem 输出的 Subject 行整段复制粘贴进 createUser 调用里,别手工改写。











