如何在 pymongo 连接的密码中转义 @?

How to escape @ in a password in pymongo connection?

我的问题是 how can i validate username password for mongodb authentication through pymongo? 的规格。

我正在尝试使用 PyMongo 3.2.2 和包含用户和密码的 URL 连接到 MongoDB 实例,如 MongoDB Docs 中所述。不同之处在于我使用的密码包含一个“@”。

一开始我只是简单的尝试连接不转义,像这样:

prefix = 'mongodb://'

user = 'user:passw_with_@_'

suffix = '@127.0.0.1:27001/'

conn = pymongo.MongoClient(prefix + user + suffix)

当然我得到了以下错误:

InvalidURI: ':' or '@' characters in a username or password must be escaped according to RFC 2396.

所以我尝试使用 urllib.quote() 转义 user:pass 部分,如下所示:

prefix = 'mongodb://'

user = urllib.quote('user:passw_with_@_')

suffix = '@127.0.0.1:27001/'

conn = pymongo.MongoClient(prefix + user + suffix)

但后来我得到了一个:

OperationFailure: Authentication failed.

(重要的是说使用 GUI MongoDB 管理工具(Robomongo,如果这很重要)我能够使用(真实)地址连接到 MongoDB和凭据。)

在上面的代码中打印用户变量生成了一个 'user:passw_with_%40_' 字符串(即 '@' 变成了 '%40')并且根据 wikipedia 这是预期的转义。

我什至尝试使用单反斜杠和双反斜杠(user = 'user:passw_with_\@_'user = 'user:passw_with_\@_')转义 @,但因 InvalidURI 异常而失败。

TL;DR;

我的问题是:如何在 MongoDB URL 的密码部分转义“@”?

您应该可以使用 urllib.quote() 对密码进行转义。虽然您应该只 quote/escape 密码,并排除 username: ; 否则 : 也将转义为 %3A.

例如:

import pymongo 
import urllib 

mongo_uri = "mongodb://username:" + urllib.quote("p@ssword") + "@127.0.0.1:27001/"
client = pymongo.MongoClient(mongo_uri)

以上代码段针对 MongoDB v3.2.x、Python v2.7 和 PyMongo v3.2.2.

进行了测试

上面的例子假设在MongoDB URI connection string:

  • 用户在 admin 数据库中创建。
  • 主机 mongod 运行 是 127.0.0.1 (localhost)
  • 分配给的端口mongod是27001

对于 Python 3.x,您可以利用 urllib.parse.quote() 使用 %xx 转义符替换密码中的特殊字符。同样的例子:

urllib.parse.quote("p@ssword")

Python 3.6.5 - 用于连接到 mlab 实例的 PyMongo 3.7.0 版本:

from pymongo import MongoClient
import urllib.parse

username = urllib.parse.quote_plus('username')
password = urllib.parse.quote_plus('password')
client = MongoClient('mongodb://%s:%s@ds00000.mlab.com:000000/recipe_app_testing' % (username, password))

这是我在不使用 flask-pymongo spun up 应用程序的情况下设法连接到 mlab MongoDB 实例的唯一方法,我需要为单元测试创​​建固定装置。

Python 3.6.5 - PyMongo 3.7.0 本地主机版本:

from pymongo import MongoClient
import urllib.parse 

username = urllib.parse.quote_plus('username')
password = urllib.parse.quote_plus('password')
client = MongoClient('mongodb://%s:%s@127.0.0.1:27001/' % (username, password))

运行 在终端中:

python -m pip install pymongo[srv]

python 文件:

import pymongo
from pymongo import MongoClient
import urllib.parse

username = urllib.parse.quote_plus('username')
password = urllib.parse.quote_plus("password")

url = "mongodb+srv://{}:{}@cluster0-0000.mongodb.net/<dbname>?retryWrites=true&w=majority".format(username, password)
# url is just an example (your url will be different)

cluster = MongoClient(url)
db = cluster['Sample']
collection = db['temporary']

刚刚信息:

MongoDB, pymongo 和 mongoengine 无法处理密码中的多个符号;

Restrictions on Database Names for Windows

/\. "$*<>:|?

Restrictions on Database Names for Unix and Linux Systems

/\. "$

https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names

包含非法符号时转义不起作用。