MongoDB C# SSL Client Certificate
本文关键字:Certificate Client SSL MongoDB | 更新日期: 2023-09-27 18:32:43
我正在尝试使用证书验证使用 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);
有谁知道如何让它工作?
意识到这已经过时了,但为了他人的利益......
如果不处理证书吊销列表,则需要关闭该设置,因为它默认处于启用状态。
clientSettings.SslSettings.CheckCertificateRevocation = false;
接下来,提供给驱动程序的 X509Certificate2 必须包含私钥。 .NET 似乎不会在 pem 文件中选取私钥,因此需要提供 .pfx 格式的证书并包含密码。
要在 openssl 中创建 pfx 文件,请执行以下操作:
openssl pkcs12 -export -in mycert.cer -inkey mycert.key -out mycert.pfx
OpenSSL 将提示您输入导出密码,请在创建 X509Certificate2 对象时使用该密码:
X509Certificate2 cert = new X509Certificate2("mycert.pfx","mypassphrase");
//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);
}
}
}
,ssl_ca_certs = @"/path/my.pem",在连接字符串中添加了这个。
设置。验证SslCertificate = false;
如果您从本地测试它/您有根证书但未颁发给您的计算机,请使用上面的行,可能会颁发给您的生产主机。
将根证书放在绝对路径中,并在连接字符串中直接引用该路径。Mongo驱动程序将负责读取私钥和所有内容。无需将其放在证书存储区或某个地方。
从 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);
}