无法使用 mongocsharpdriver 2.7.0 连接到 MongoDb(使用身份验证)

Unable to connect to MongoDb (using authentication) using mongocsharpdriver 2.7.0

我创建了一个示例 C# 控制台应用程序以连接到 docker 上 CentOS 机器上托管的 mongodb。

创建容器的命令如下:

docker run -d --name mongodb-container -p 2020:27017 -v /home/mongodb_data:/var/lib/mongodb/data -v /home/mongodb_log:/var/log/mongodb -v /home/mongod.conf:/etc/mongod.conf -e MONGO_INITDB_ROOT_USERNAME=mongoadmin -e MONGO_INITDB_ROOT_PASSWORD=secret mongo

系统IP:172.17.103.158
Mongodb docker 端口:2020

现在开始使用 C# 代码

class users
    {
        [BsonId]
        public ObjectId _Id { get; set; }

        [BsonElement]
        public string name { get; set; }
    }

MongoContext Class

public class MongoContext
    {
        IMongoClient _client;
        public readonly IMongoDatabase _database;

        public MongoContext()
        {
            MongoCredential credential = MongoCredential.CreateCredential(ConfigurationManager.AppSettings["MongoDatabaseName"], ConfigurationManager.AppSettings["MongoUsername"], ConfigurationManager.AppSettings["MongoPassword"]);

            var settings = new MongoClientSettings
            {
                Credential = credential,
                VerifySslCertificate = false,
                ConnectionMode = ConnectionMode.ReplicaSet,
                ReplicaSetName = ConfigurationManager.AppSettings["MongoDatabaseName"],
                UseSsl = false,
                Server = new MongoServerAddress(ConfigurationManager.AppSettings["MongoHost"], Convert.ToInt32(ConfigurationManager.AppSettings["MongoPort"]))
            };

            _client = new MongoClient(settings);
            _database = _client.GetDatabase(ConfigurationManager.AppSettings["MongoDatabaseName"]);
        }
    }

网络配置:

<configuration>


<appSettings>
    <add key="MongoDatabaseName" value="clientdb" />
    <add key="MongoUsername" value="mongoadmin" />
    <add key="MongoPassword" value="secret" />
    <add key="MongoPort" value="2020" />
    <add key="MongoHost" value="172.17.103.158" />
  </appSettings>

</configuration>

查看用户

static List<users> ViewUsers()
    {
        try
        {
            MongoContext db = new MongoContext();
            IMongoCollection<users> Table1 = db._database.GetCollection<users>("users");

            return Table1.AsQueryable().ToList();
        }
        catch (Exception ex) { throw ex; }
    }

错误:

{"A timeout occured after 30000ms selecting a server using CompositeServerSelector{
  Selectors = MongoDB.Driver.MongoClient+AreSessionsSupportedServerSelector, LatencyLimitingServerSelector{
    AllowedLatencyRange = 00:00:00.0150000 } }.
Client view of cluster state is {
  ClusterId : \"1\",
  ConnectionMode : \"Automatic\",
  Type : \"Unknown\",
  State : \"Disconnected\",
  Servers : [{
    ServerId: \"{
      ClusterId : 1,
      EndPoint : \"172.17.103.158:2020\" }\",
    EndPoint: \"172.17.103.158:2020\",
    State: \"Disconnected\",
    Type: \"Unknown\",
    HeartbeatException: \"MongoDB.Driver.MongoConnectionException: An exception occurred while opening a connection to the server. 
        ---> MongoDB.Driver.MongoAuthenticationException: Unable to authenticate using sasl protocol mechanism SCRAM-SHA-1. 
        ---> MongoDB.Driver.MongoCommandException: Command saslStart failed: Authentication failed..\r\n   
      at MongoDB.Driver.Core.WireProtocol.CommandUsingQueryMessageWireProtocol`1.ProcessReply(ConnectionId connectionId, ReplyMessage`1 reply)\r\n   
      at MongoDB.Driver.Core.WireProtocol.CommandUsingQueryMessageWireProtocol`1.<ExecuteAsync>d__14.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   
      at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   
      at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   
      at MongoDB.Driver.Core.Authentication.SaslAuthenticator.<AuthenticateAsync>d__7.MoveNext()\r\n   --- End of inner exception stack trace ---\r\n   
      at MongoDB.Driver.Core.Authentication.SaslAuthenticator.<AuthenticateAsync>d__7.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   
      at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   
      at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   
      at MongoDB.Driver.Core.Authentication.DefaultAuthenticator.<AuthenticateAsync>d__7.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   
      at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   
      at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   
      at MongoDB.Driver.Core.Authentication.AuthenticationHelper.<AuthenticateAsync>d__1.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   
      at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   
      at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   
      at MongoDB.Driver.Core.Connections.ConnectionInitializer.<InitializeConnectionAsync>d__3.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   
      at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   
      at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   
      at MongoDB.Driver.Core.Connections.BinaryConnection.<OpenHelperAsync>d__48.MoveNext()\r\n   --- End of inner exception stack trace ---\r\n   
      at MongoDB.Driver.Core.Connections.BinaryConnection.<OpenHelperAsync>d__48.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   
      at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   
      at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   
      at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)\r\n   
      at MongoDB.Driver.Core.Servers.ServerMonitor.<HeartbeatAsync>d__27.MoveNext()\" }] }."}

在简短的错误消息中:

{"A timeout occured after 30000ms selecting a server using CompositeServerSelector{
  Selectors = MongoDB.Driver.MongoClient+AreSessionsSupportedServerSelector, LatencyLimitingServerSelector{
    AllowedLatencyRange = 00:00:00.0150000 } }.
Client view of cluster state is {
  ClusterId : \"1\",
  ConnectionMode : \"Automatic\",
  Type : \"Unknown\",
  State : \"Disconnected\",
  Servers : [{
    ServerId: \"{
      ClusterId : 1,
      EndPoint : \"172.17.103.158:2020\" }\",
    EndPoint: \"172.17.103.158:2020\",
    State: \"Disconnected\",
    Type: \"Unknown\",
    HeartbeatException: \"MongoDB.Driver.MongoConnectionException: An exception occurred while opening a connection to the server. 
      ---> MongoDB.Driver.MongoAuthenticationException: Unable to authenticate using sasl protocol mechanism SCRAM-SHA-1. 
      ---> MongoDB.Driver.MongoCommandException: Command saslStart failed: Authentication failed..

当 mongo 数据库受到用户名和密码保护时,我遇到了这个问题,否则不会。

虽然 MongoDb Compass 在这两种情况下仍然能够连接到 mongo 数据库。

我的问题是:为什么在 db 上应用身份验证时,c# 代码无法连接到 mongodb。

尝试过的解决方案:

  1. 使用 uri 连接:

    mongodb://mongoadmin:secret@172.17.103.158:2020/clientdb
    
  2. 已编辑mongod.config => BindIp 127.0.0.1, 172.17.103.17(我的系统 IP)

  3. 使用 SCRAM-SHA-1 机制

在mongod.conf中添加你本地的ip到bind_ip

  • mongod.conf 文件

    bind_ip = 127.0.0.1,192.168.xxx.xxxx

其中:

  • 127.0.0.1 允许来自同一台机器的连接
  • 192.168.xxx.xxxx 允许来自此 ip 的连接

Check This

确保您使用的用户名存在于 clientdb 数据库中

要将用户添加到 clientdb 数据库,您可以关注

use clientdb

db.createUser(
   {
     user: "mongoadmin",
     pwd: "secret",
     roles:
       [
         { role: "root", db: "admin" }
       ]
   }
)

关注这个linkMongo Site 并查看

部分

The Database Component :
The database component is optional and is used to indicate which database to authenticate against. When the database component is not provided, the “admin” database is used.

问题是您正在为 clientdb 验证 mongoadmin 用户。但是 mongoadmin 用户已通过 admin db 的身份验证。获取mongoadmin用户认证后就可以访问clientdb了。

下面是使用 URI 方法的示例:

        IMongoClient _client;
        public readonly IMongoDatabase _database;

        public MongoContext_URIBased()
        {
            var mongoUrl = new MongoUrl("mongodb://mongoadmin:secret@172.17.103.158:2020/admin");
            _client = new MongoClient(mongoUrl);
            _database = _client.GetDatabase("clientdb");
        } 

并且根据您的代码,以下将起作用:

你的配置文件应该是这样的:

<appSettings>
<add key="MongoMasterDatabaseName" value="admin" />
<add key="MongoUsername" value="mongoadmin" />
<add key="MongoPassword" value="secret" />
<add key="MongoPort" value="2020" />
<add key="MongoHost" value="172.17.103.158" />
<add key="MongoClientDatabaseName" value="clientDb" />


</appSettings>

和 C# 代码:

public class MongoContext
    {
        IMongoClient _client;
        public readonly IMongoDatabase _database;

        public MongoContext()
        {
            MongoCredential credential = MongoCredential.CreateCredential(ConfigurationManager.AppSettings["MongoMasterDatabaseName"], ConfigurationManager.AppSettings["MongoUsername"], ConfigurationManager.AppSettings["MongoPassword"]);
            var settings = new MongoClientSettings
            {
                Credential = credential,
                Server = new MongoServerAddress(, Convert.ToInt32(ConfigurationManager.AppSettings["MongoPort"]))
            };
            _client = new MongoClient(settings);
            _database = _client.GetDatabase(ConfigurationManager.AppSettings["MongoClientDatabaseName"]);
        }
    }

如您所见,mongoadmin 用户首先通过 admin db 的身份验证。然后你可以连接到 clientdb