【.NET Core】|?總結/Edison Zhou
大家好,我是Edison。
最近有一個ASP.NET Core通過SSL證書訪問MongoDB的需求,但是在網上發現資料很少,于是調查了一番,做了如下的筆記,希望對你有用。
背景
在實際場景中,開發環境的MongoDB服務器一般沒有要求通過SSL方式來登陸,但是生產環境的MongoDB服務器通常都會基于安全要求基于SSL方式來訪問,這就要求客戶端應用需要通過SSL證書來和MongoDB服務器進行通信驗證后才能正常讀取和寫入數據。
那么,在ASP.NET Core應用中應該如何修改匹配呢?今天,我們就來看一看。
修改
通過學習MongoDB.Driver后,在實例化MongoClient時可以通過傳遞一個MongoClientSettings類來進行自定義參數的實例化,而這個MongoClientSettings類提供的參數比較豐富,我們可以將這些參數配置在appsettings中進行分環境的自定義。
var mongoClient = new MongoClient(new MongoClientSettings());
因此,我們可以寫一個MongoSettings類來讀取appsettings中的配置生成一個MongoClientSettings,這里給出一個參考示例。
using MongoDB.Driver;
using System.Security.Cryptography.X509Certificates;namespace EDT.Todo.Data.Persistance
{/// <summary>/// Generate MongoClientSettings/// </summary>public class MongoSettings{public string Servers { get; set; }public int Port { get; set; } = 27017;public string ReplicaSetName { get; set; }public string DatabaseName { get; set; }public string DefaultCollectionName { get; set; } = string.Empty;public string ApplicationName { get; set; }public string UserName { get; set; }public string Password { get; set; }public string AuthDatabaseName { get; set; } = string.Empty;public string CustomProperties { get; set; } = string.Empty;public bool UseTLS { get; set; } = false;public bool AllowInsecureTLS { get; set; } = true;public string ClientCertificatePath { get; set; } = string.Empty;public bool StoreCertificateInKeyStore { get; set; } = false;public MongoClientSettings GetMongoClientSettings(){if (string.IsNullOrWhiteSpace(Servers))throw new ArgumentNullException("Mongo Servers Configuration is Missing!");if (string.IsNullOrWhiteSpace(UserName) || string.IsNullOrWhiteSpace(Password))throw new ArgumentNullException("Mongo Account Configuration is Missing!");// Base ConfigurationMongoClientSettings settings = new MongoClientSettings{ApplicationName = ApplicationName,ReplicaSetName = ReplicaSetName};// Credentialif (string.IsNullOrWhiteSpace(AuthDatabaseName))settings.Credential = MongoCredential.CreateCredential(DatabaseName, UserName, Password);elsesettings.Credential = MongoCredential.CreateCredential(AuthDatabaseName, UserName, AuthDatabaseName);// Serversvar mongoServers = Servers.Split(",", StringSplitOptions.RemoveEmptyEntries).ToList();if (mongoServers.Count == 1){settings.Server = new MongoServerAddress(mongoServers.First(), Port);settings.DirectConnection = true;}if (mongoServers.Count > 1){var mongoServerAddresses = new List<MongoServerAddress>();foreach (var mongoServer in mongoServers){var mongoServerAddress = new MongoServerAddress(mongoServer, Port);mongoServerAddresses.Add(mongoServerAddress);}settings.Servers = mongoServerAddresses;settings.DirectConnection = false;}// SSLif (UseTLS){settings.UseTls = true;settings.AllowInsecureTls = AllowInsecureTLS;if (string.IsNullOrWhiteSpace(ClientCertificatePath))throw new ArgumentNullException("ClientCertificatePath is Missing!");var certs = new List<X509Certificate> { new X509Certificate2(ClientCertificatePath) };settings.SslSettings = new SslSettings();settings.SslSettings.ClientCertificates = certs;settings.SslSettings.EnabledSslProtocols = System.Security.Authentication.SslProtocols.Tls13;}return settings;}}
}
對于原有的Repository類,我們則需要做一點點修改,從IoC容器中獲取MongoSettings的實例,并通過調用GetMongoClientSettings方法獲取到生成的這個具體的MongoClientSettings對象:
public class TodoItemRepository : ITodoItemRepository
{private readonly ILogger<TodoItemRepository> _logger;private readonly IMongoCollection<TodoItem> _todoItems;public TodoItemRepository(MongoSettings settings, ILogger<TodoItemRepository> logger){var mongoClient = new MongoClient(settings.GetMongoClientSettings());var mongoDatabase = mongoClient.GetDatabase(settings.DatabaseName);_todoItems = mongoDatabase.GetCollection<TodoItem>(settings.DefaultCollectionName);_logger = logger;}......
}
在Program.cs中將MongoSettings和appsettings中的配置綁定:
builder.Services.Configure<MongoSettings>(builder.Configuration.GetSection("MongoDatabase"));
builder.Services.AddSingleton(sp =>sp.GetRequiredService<IOptions<MongoSettings>>().Value);
......
builder.Services.AddSingleton<ITodoItemRepository, TodoItemRepository>();
針對Development環境的appsettings:
{...... "MongoDatabase": {"Servers": "dev.mongodb01.com,dev.mongodb01.com,dev.mongodb01.com","Port": 27017,"ReplicaSetName": "testrplica","DatabaseName": "TestDB","DefaultCollectionName": "TodoItems","ApplicationName": "Todo","UserName": "dev_mongo_user","Password": "passwordfordevuser","UseTLS": false}
}
針對Production環境的appsettings:
{...... "MongoDatabase": {"Servers": "prd.mongo01.com,prd.mongo02.com,prd.mongo03.com","Port": 27007,"ReplicaSetName": "testreplica","DatabaseName": "TestDB","DefaultCollectionName": "TodoItems","ApplicationName": "Todo","UserName": "prd_mongo_user","Password": "passwordforprduser","UseTLS": true,"AllowInsecureTLS": true,"ClientCertificatePath": "resources/certificates/intranet_server_ca.cer"}
}
既然是通過證書訪問,那么我們得告訴ASP.NET Core這個證書放在什么位置,本文示例是放在這個ASP.NET Core應用目錄下的,在實際中建議由運維管理員統一放在一個中心服務器位置,掛載到容器內部可以訪問,從而保證證書的安全。如果使用了K8s,還可以將證書作為Secret統一存放。
小結
本文介紹了在ASP.NET Core中如何配置和實現基于SSL證書的方式訪問MongoDB數據庫,希望對你有所幫助!
參考資料
MongoDB.Driver Doc
年終總結:Edison的2021年終總結
數字化轉型:我在傳統企業做數字化轉型
C#刷題:C#刷劍指Offer算法題系列文章目錄
.NET面試:.NET開發面試知識體系
.NET大會:2020年中國.NET開發者大會PDF資料