MongoDB C# SSL 客户端证书

7

我正在尝试使用C#驱动程序和证书验证来建立与MongoDB的安全连接,但是我遇到了以下错误:

无法连接到服务器localhost:27017:无法从传输连接中读取数据:已建立的连接被您的主机上的软件中止。

这是来自MongoDB的错误信息:

[initandlisten] connection accepted from 127.0.0.1:26163 #2 (1 connection now open)
[conn2] ERROR: no SSL certificate provided by peer; connection rejected
[conn2] SocketException handling request, closing client connection: 9001 socket exception [CONNECT_ERROR]

当我使用证书通过mongo shell连接到MongoDB时,它可以正常工作。

var connectionString = "mongodb://localhost";
var clientSettings = MongoClientSettings.FromUrl(new MongoUrl(connectionString));
clientSettings.SslSettings = new SslSettings();
clientSettings.UseSsl = true;
clientSettings.SslSettings.ClientCertificates = new List<X509Certificate>()
    {
        new X509Certificate("cert.pem")
    };
clientSettings.SslSettings.EnabledSslProtocols = SslProtocols.Default;
clientSettings.SslSettings.ClientCertificateSelectionCallback =
    (sender, host, certificates, certificate, issuers) => clientSettings.SslSettings.ClientCertificates.ToList()[0];
clientSettings.SslSettings.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
var client = new MongoClient(clientSettings);

有人知道如何让这个工作起来吗?



如果您使用机器名称而不是本地主机名,它是否有效? - WiredPrairie
不,我已经尝试过使用 IP 地址和主机名,但仍然出现相同的错误。 - Stegzilla
clientSettings.SslSettings.ClientCertificateSelectionCallback = (发送者,主机,证书,证书,发行者)=> clientSettings.SslSettings.ClientCertificates.ToList()[0]; - 此行在ToList处抛出错误 - thePolarExpress88
4个回答

10

了解到这篇内容已经过时,但是为了其他人的利益...

如果你不处理证书吊销列表,你需要关闭此设置,因为它默认是启用的。

clientSettings.SslSettings.CheckCertificateRevocation = false;

接下来,你提供给驱动程序的X509Certificate2必须包含私钥。.NET似乎无法从pem文件中获取私钥,因此需要使用.pfx格式的证书并包含密码。

使用openssl创建pfx文件:

openssl pkcs12 -export -in mycert.cer -inkey mycert.key -out mycert.pfx

在创建X509Certificate2对象时,OpenSSL将提示您输入导出密码短语,请使用该密码短语:

X509Certificate2 cert = new X509Certificate2("mycert.pfx","mypassphrase");

1

//struggled a lot to figure out this

using MongoDB.Bson;
using MongoDB.Driver;

namespace Mongo_AWS
{
    internal class Program
    {
        private static void Main(string[] args)
        {

//Mention cert file in connection string itself or put at your executable location
            string connectionString = @"mongodb://user:pwd@localhost:9999/?ssl=true&ssl_ca_certs=C:\Users\sivaram\Downloads\my.pem";

            MongoClientSettings settings = MongoClientSettings.FromUrl(new MongoUrl(connectionString));
            
            //Disable certificate verification, if it is not issued for you
            settings.VerifySslCertificate = false;
            MongoClient client = new MongoClient(settings);
            IMongoDatabase database = client.GetDatabase("test");
            IMongoCollection<BsonDocument> collection = database.GetCollection<BsonDocument>("numbers");
            System.Collections.Generic.List<BsonDocument> temp = collection.Find(new BsonDocument()).ToList();
            BsonDocument docToInsert = new BsonDocument { { "sivaram-Pi", 3.14159 } };
            collection.InsertOne(docToInsert);
        }
    }
}


1
请您能否添加一些描述,说明您是如何解决这个问题的。 - Diego Malone
ssl_ca_certs,在连接字符串中添加此内容。如果您正在本地测试或您拥有根证书但未提供给您的计算机,可以使用此行:settings.VerifySslCertificate = false; 可能已发行到您的生产主机.. 代码中也添加了内联注释。 - Sivaramakrishna Movva
ssl_ca_certs不受支持。有没有其他替代方案? - Mowgli

0

ssl_ca_certs = @"/path/my.pem",在连接字符串中添加此行。

settings.VerifySslCertificate = false;

如果您正在本地测试或根证书不是针对您的机器而发放,可能是针对您的生产主机,请使用上述行。

将根证书放在绝对路径中,并直接在连接字符串中引用该路径。Mongo驱动程序将负责读取私钥等。无需将其放在证书存储区或其他地方。


0
借鉴tyjen的回答,这可以完全使用C#完成。假设您有一个PEM格式文件,其中包含公钥和私钥,您可以使用以下代码创建有效的X509证书(在此用例中假设您有一个带有公钥和私有RSA密钥的PEM文件):
using System.Text;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

using MongoDB.Driver;

function X509Certificate2 GetX509Pfx(String pem) {
    // Note that cert is `IDisposable`
    var cert = new X509Certificate2(Encoding.UTF8.GetBytes(pem)))
    if (cert.HasPrivateKey) {
        return cert;
    } else {
        // Note that rsa is `IDisposable`
        var rsa = RSA.Create();
        rsa.ImportFromPem(pem.AsSpan());
        return cert.CopyWithPrivateKey(rsa);
    }
}

function IMongoClient GetMongoClient(String connectionString, String pem) {
    var cert = GetX509Pfx(pem);
    var settings = MongoClientSettings.FromConnectionString(connectionString);
    settings.ServerApi = new ServerApi(ServerApiVersion.V1),
    settings.Credential = MongoCredential.CreateMongoX509Credential(cert.Subject),
    settings.SslSettings = new SslSettings {
        ClientCertificates = new List<X509Certificates> { cert }
    }

    return new MongoClient(settings);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接