Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to escape @ in a password in pymongo connection?

Tags:

My question is a specification of how can i validate username password for mongodb authentication through pymongo?.

I'm trying to connect to a MongoDB instance using PyMongo 3.2.2 and a URL that contains the user and password, as explained in MongoDB Docs. The difference is that the password I'm using contains a '@'.

At first I simply tried to connect without escaping, like this:

prefix = 'mongodb://'

user = 'user:passw_with_@_'

suffix = '@127.0.0.1:27001/'

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

Naturally I got the following error:

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

So I tried escaping the user:pass part using urllib.quote() like this:

prefix = 'mongodb://'

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

suffix = '@127.0.0.1:27001/'

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

but then I got a:

OperationFailure: Authentication failed. 

(Important to say that using a GUI MongoDB Management Tool (Robomongo, if that matters) I'm able to connect to the MongoDB using the (real) address and credentials.)

Printing user variable in the code above generated a 'user:passw_with_%40_' String (that is '@' became '%40') and according to wikipedia that's the expected escaping.

I even tried escaping the @ with single and double backslashes (user = 'user:passw_with_\\@_' and user = 'user:passw_with_\@_'), but those failed with the InvalidURI exception.

TL;DR;

My question is: How do I escape a '@' in the password part of a MongoDB URL?

like image 829
gmauch Avatar asked Aug 30 '16 22:08

gmauch


People also ask

How do I pass MongoClient username and password?

const MongoClient = require('mongodb'). MongoClient; (async() => { const db = await MongoClient. connect('mongodb://adminUsername:adminPassword@localhost:27017/mydb?authSource=admin'); // now you can use db: const collection = await db.

Do I need to close PyMongo connection?

There's no need to close a Connection instance, it will clean up after itself when Python garbage collects it. You should use MongoClient instead of Connection ; Connection is deprecated. To take advantage of connection pooling, you could create one MongoClient that lasts for the entire life of your process.

What is MongoClient in PyMongo?

The class MongoClient enables you to make successful MongoDB server connections with your code. The MongoClient can accomplish this with client instances.

How does connection pooling work in PyMongo?

How does connection pooling work in PyMongo? ¶ Every MongoClient instance has a built-in connection pool per server in your MongoDB topology. These pools open sockets on demand to support the number of concurrent MongoDB operations that your multi-threaded application requires.


2 Answers

You should be able to escape the password using urllib.quote(). Although you should only quote/escape the password, and exclude the username: ; otherwise the : will also be escaped into %3A.

For example:

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

The above snippet was tested for MongoDB v3.2.x, Python v2.7, and PyMongo v3.2.2.

The example above assumed in the MongoDB URI connection string:

  • The user is created in the admin database.
  • The host mongod running on is 127.0.0.1 (localhost)
  • The port mongod assigned to is 27001

For Python 3.x, you can utilise urllib.parse.quote() to replace special characters in your password using the %xx escape. For example:

url.parse.quote("p@ssword") 
like image 57
Wan Bachtiar Avatar answered Nov 14 '22 15:11

Wan Bachtiar


Python 3.6.5 - PyMongo 3.7.0 version for connecting to an mlab instance:

from pymongo import MongoClient import urllib.parse  username = urllib.parse.quote_plus('username') password = urllib.parse.quote_plus('password') client = MongoClient('mongodb://%s:%[email protected]:000000/recipe_app_testing' % (username, password)) 

This is the only way I have managed to connect to the mlab MongoDB instance without using flask-pymongo spun up app, I needed to create fixtures for unit tests.

Python 3.6.5 - PyMongo 3.7.0 localhost version:

from pymongo import MongoClient import urllib.parse   username = urllib.parse.quote_plus('username') password = urllib.parse.quote_plus('password') client = MongoClient('mongodb://%s:%[email protected]:27001/' % (username, password)) 
like image 33
Conor Avatar answered Nov 14 '22 16:11

Conor