使用PyMongo连接MongoDB时认证失败问题求助
MongoDB认证失败:PyMongo连接失败但mongo shell成功
问题描述
使用Python的PyMongo连接MongoDB时触发认证失败错误,但通过mongo shell命令可正常连接并获取结果,相关代码及错误信息如下:
正常工作的mongo shell命令
mongo -u MYUSER -p MYPASSWD 127.0.0.1:27017/MYDB --authenticationDatabase admin --eval "printjson(db.getCollectionNames())"
报错的Python代码
import pymongo import urllib.parse host = "127.0.0.1" port = 27017 user = "MYUSER" password = "MYPASSWD" dbname = "MYDB" client = pymongo.MongoClient(f'mongodb://"{user}:{urllib.parse.quote_plus(password)}@{host}:{port}/{dbname}?authSource=admin') #db = client.get_database() db = client[dbname] collection_vhs = db['vhs'] result = collection_vhs.find({"idSimple":"/01/"}) for doc in result: print(result)
报错信息
(env) root@MYHOST:~# python3 /etc/zabbix/scripts/mongodb_field_idSimple.py Traceback (most recent call last): File "/etc/zabbix/scripts/mongodb_field_idSimple.py", line 21, in <module> for doc in result: File "/root/env/lib64/python3.6/site-packages/pymongo/cursor.py", line 1248, in next if len(self.__data) or self._refresh(): File "/root/env/lib64/python3.6/site-packages/pymongo/cursor.py", line 1165, in _refresh self.__send_message(q) File "/root/env/lib64/python3.6/site-packages/pymongo/cursor.py", line 1053, in __send_message operation, self._unpack_response, address=self.__address File "/root/env/lib64/python3.6/site-packages/pymongo/mongo_client.py", line 1272, in _run_operation retryable=isinstance(operation, message._Query), File "/root/env/lib64/python3.6/site-packages/pymongo/mongo_client.py", line 1365, in _retryable_read with self._socket_from_server(read_pref, server, session) as (sock_info, read_pref): File "/usr/lib64/python3.6/contextlib.py", line 81, in __enter__ return next(self.gen) File "/root/env/lib64/python3.6/site-packages/pymongo/mongo_client.py", line 1221, in _socket_from_server with self._get_socket(server, session) as sock_info: File "/usr/lib64/python3.6/contextlib.py", line 81, in __enter__ return next(self.gen) File "/root/env/lib64/python3.6/site-packages/pymongo/mongo_client.py", line 1156, in _get_socket with server.get_socket(handler=err_handler) as sock_info: File "/usr/lib64/python3.6/contextlib.py", line 81, in __enter__ return next(self.gen) File "/root/env/lib64/python3.6/site-packages/pymongo/pool.py", line 1379, in get_socket sock_info = self._get_socket() File "/root/env/lib64/python3.6/site-packages/pymongo/pool.py", line 1489, in _get_socket sock_info = self.connect() File "/root/env/lib64/python3.6/site-packages/pymongo/pool.py", line 1350, in connect sock_info.authenticate() File "/root/env/lib64/python3.6/site-packages/pymongo/pool.py", line 845, in authenticate auth.authenticate(creds, self) File "/root/env/lib64/python3.6/site-packages/pymongo/auth.py", line 549, in authenticate auth_func(credentials, sock_info) File "/root/env/lib64/python3.6/site-packages/pymongo/auth.py", line 475, in _authenticate_default return _authenticate_scram(credentials, sock_info, "SCRAM-SHA-1") File "/root/env/lib64/python3.6/site-packages/pymongo/auth.py", line 201, in _authenticate_scram res = sock_info.command(source, cmd) File "/root/env/lib64/python3.6/site-packages/pymongo/pool.py", line 764, in command exhaust_allowed=exhaust_allowed, File "/root/env/lib64/python3.6/site-packages/pymongo/network.py", line 164, in command parse_write_concern_error=parse_write_concern_error, File "/root/env/lib64/python3.6/site-packages/pymongo/helpers.py", line 180, in _check_command_response raise OperationFailure(errmsg, code, response, max_wire_version) pymongo.errors.OperationFailure: Authentication failed., full error: {'ok': 0.0, 'errmsg': 'Authentication failed.', 'code': 18, 'codeName': 'AuthenticationFailed'}
问题原因
连接字符串中多了多余的双引号,导致用户名被错误地包含前引号(实际传递的用户名为"MYUSER),与真实用户名MYUSER不符,触发认证失败。
错误的连接字符串构造:
f'mongodb://"{user}:{urllib.parse.quote_plus(password)}@{host}:{port}/{dbname}?authSource=admin'
{user}前的"完全冗余且未闭合,是核心问题。
修正方案
移除连接字符串中的多余双引号,同时推荐使用参数式构造方式(可读性更强,避免字符串拼接错误),另外代码中print(result)需改为print(doc),否则打印的是游标对象而非文档内容。
修正后的代码
import pymongo import urllib.parse host = "127.0.0.1" port = 27017 user = "MYUSER" password = "MYPASSWD" dbname = "MYDB" # 方式1:修复后的字符串拼接 client = pymongo.MongoClient(f'mongodb://{user}:{urllib.parse.quote_plus(password)}@{host}:{port}/{dbname}?authSource=admin') # 方式2:更推荐的参数式构造(可读性更强,不易出错) # client = pymongo.MongoClient( # host=host, # port=port, # username=user, # password=password, # authSource='admin', # authMechanism='SCRAM-SHA-1' # 可选,根据MongoDB认证机制调整 # ) db = client[dbname] collection_vhs = db['vhs'] result = collection_vhs.find({"idSimple":"/01/"}) for doc in result: print(doc) # 改为打印单个文档对象
内容的提问来源于stack exchange,提问作者sivsoft
相关产品推荐
相关产品推荐

