#mongodb #mongodb-.net-driver
Вопрос:
Я пытаюсь подключить API .Net Core к моему защищенному SSL MongoDB. Я могу подключиться с помощью Mongo Compass, поэтому я уверен, что проблема не в моей конфигурации MongoDB.
Все работало нормально до того, как сертификаты были добавлены в MongoDB, и, как вы увидите, стек указывает прямо на сертификаты. Я просто не знаю, как это исправить.
Я не смог найти много документации о том, как реализовать SslSettings в драйвере MongoDB, поэтому я собираю это вместе из разных источников и поэтому задаю вопросы.
Проблема, похоже, возникает, когда мой API подключается к Mongo. Я получаю следующее исключение.
Значение не может быть равно нулю. (Параметр «источник»)
Дамп стека указывает прямо на то, что сертификаты X509 являются отсутствующим / нулевым значением.
at System.Linq.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument) at System.Linq.Enumerable.Cast[TResult](IEnumerable source) at MongoDB.Driver.SslSettings.X509CertificateCollectionEqualityComparer.Equals(X509CertificateCollection lhs, X509CertificateCollection rhs) at MongoDB.Driver.SslSettings.Equals(Object obj) at System.Object.Equals(Object objA, Object objB) at MongoDB.Driver.ClusterKey.Equals(Object obj) at System.Collections.Generic.ObjectEqualityComparer`1.Equals(T x, T y) at System.Collections.Generic.Dictionary`2.FindValue(TKey key) at System.Collections.Generic.Dictionary`2.TryGetValue(TKey key, TValueamp; value) at MongoDB.Driver.ClusterRegistry.GetOrCreateCluster(ClusterKey clusterKey) at MongoDB.Driver.MongoClient..ctor(MongoClientSettings settings) at MongoDB.Driver.MongoClient..ctor(String connectionString) at Bullies.API.Endpoints.Users.UserService..ctor(IOptions`1 config, IMediator mediator) in C:Users...Demo.APIEndpointsUsersUserService.cs:line 38 at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions) at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.lt;gt;c__DisplayClass1_0.lt;RealizeServicegt;b__0(ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) at Demo.API.HostedServices.SubscriptionHostedService.lt;ExecuteAsyncgt;d__2.MoveNext() in C:Users...Demo.APIHostedServicesSubscriptionHostedService.cs:line 32 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult() at Microsoft.Extensions.Hosting.Internal.Host.lt;StartAsyncgt;d__9.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult() at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.lt;RunAsyncgt;d__4.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.lt;RunAsyncgt;d__4.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host) at Demo.API.Program.Main(String[] args) in C:...Demo.APIProgram.cs:line 22
строка подключения appsettings.json
mongodb://user:pass@localmongo:12345/MyDb?authSource=adminamp;readPreference=primaryamp;appname=demoapiamp;ssl=true
AccessMongoClass.cs
MongoCredential creds = MongoCredential.CreateMongoCRCredential("localmongo:12345", "user", "pass"); var clientCertificate = new Listlt;X509Certificategt;() { new X509Certificate("Path\...\mysite_com.pfx", "privateKeyPassword") }; MongoClientSettings settingz = new MongoClientSettings(); settingz.ApplicationName = "demo-api"; settingz.Credential = creds; settingz.SslSettings = new SslSettings() { CheckCertificateRevocation = false, //EnabledSslProtocols = System.Security.Authentication.SslProtocols.Tls12, ClientCertificates = clientCertificate, ClientCertificateSelectionCallback = (sender, host, certificates, certificate, issuers) =gt; clientCertificate.ToList()[0], ServerCertificateValidationCallback = (sender, certificate, chain, errors) =gt; true }; MongoClient client = new MongoClient(settingz);
На стороне mongodb я вижу эту ошибку:
"ctx":"conn7","msg":"Interrupted operation as its client disconnected","attr":{"opId":1731}}
Журнал Монго ОЧЕНЬ длинный, поэтому я просто выбираю то, что считаю ключевой строкой. Если вы хотите увидеть что-то еще, я могу легко добавить это.
Я бы подумал, что предоставил сертификаты X509, но, очевидно, мне чего-то не хватает.
Ответ №1:
Я предполагаю, что вы не увидите этого исключения, если просто создадите нового клиента и увидите полную ClusterRegistry.GetOrCreateCluster
трассировку стека . Эта логика вызывается, когда драйвер пытается повторно использовать ранее созданный кластер, хранящийся в статическом хранилище( ClusterRegistry
). В вашем случае это выглядит так, как будто вы создаете 2 mongoClient
с из настроек, подобных этому:
var clientSettings1 = new MongoClientSettings() { SslSettings = new SslSettings { ClientCertificates = new X509Certificate2[] { new X509Certificate2(@"path", "pass") } } }; // create client 1 var clientSettings2 = new MongoClientSettings() { SslSettings = new SslSettings { ClientCertificates = null } }; // create client 2
если это так, это ошибка в драйвере, постарайтесь не устанавливать значение null в ClientCertificates, например, вы можете назначить пустую коллекцию
Комментарии:
1. На самом деле я получаю ту же ошибку, просто используя строку подключения. Именно это побудило меня использовать более подробную попытку в операции с определением сертификатов x509. //Клиент MongoClient = новый(_mongoSettings. Строка подключения);
2. Я не думаю, что вы можете настроить сертификат x509 только с помощью строки подключения ,но ключевые моменты:1.при создании
new MongoClient
драйвер фактически пытается найти ранее созданные mongoClients, если он найден, то он пытается проверить, имеет ли найденный клиент те же настройки MongoClient, что и клиент, который вы собираетесь создать. 2. Для того он звонитMongoClientSettings.Equals
, что по очереди звонитSslSettings.Equals
, что по очереди звонитEquals
X509CertificateCollection
. И в этом методе есть ошибка, если правоcollection
равно нулю, что приводит к ошибке, которую вы видите