Autenticación después de elegir la base de datos

Tengo 3 bases de datos en mi servidor MongoDB. Estoy usando pymongo para hacer algunos scripts con Python3.

Quiero usar las últimas versiones y prácticas. Una vez que abro el cliente y escojo la base de datos, la API para pymongo.MongoClient. [‘Mydatabase’]. Authenticate está en desuso. https://api.mongodb.com/python/current/api/pymongo/database.html

La autenticación antes de elegir la base de datos (mientras se marca el cliente) no parece fluir hacia la base de datos. No solo para pymongo, sino también cuando uso mongo shell. Así que tengo la sensación de que este es el problema.

script.py

import pymongo from pymongo import MongoClient u = getUser() # function which prompts for username p = getPassword() # getpass.getpass('Password') uri = formatUri(u, p) # formats 'mongodb://%s:%s@%s'.format(user, password, host) client = MongoClient(uri) db = client['mydb'] col = db.mycollection for doc in col.find(): print(doc) 

Recibo el error de que no estoy autorizado para la base de datos. Sé que mi cuenta funciona en shell, pero primero tengo que marcar el cliente, luego usar la base de datos y luego la autenticación.

Aquí hay un ejemplo de shell mongo:

 $ mongo MongoDB shell version: v3.4.10 Connecting to: mongodb://127.0.0.1:port MongoDB server version: v3.4.10 > use mydb switched to mydb > db.auth("user", "pass") 1 

¿Alguna idea de cómo puedo autenticarme después de seleccionar la base de datos o una vez que use la base de datos recuerda el contexto con el que marcé?

Parece que te faltan algunos conceptos aquí, así que básicamente te responderé como una “guía” de lo que deberías estar haciendo. Por lo tanto, la “autenticación” no es realmente algo que usted hace “después de” la conexión, sino que necesita estar “buscando en el lugar correcto” cuando realmente intenta autenticar.

Podemos comenzar esencialmente siguiendo el proceso descrito en Habilitar autenticación desde la documentación principal, pero modificado específicamente porque desea ejecutar esta “prueba” en su propia cuenta de usuario y directorio local.

Pasos de revisión – Directamente de la documentación

Por lo tanto, primero querría elegir un directorio de trabajo local y crear una ruta para los archivos de almacenamiento de la base de datos que se encuentran debajo. En los sistemas basados ​​en * nix puedes hacer algo como:

 mkdir -p scratch/data/db cd scratch 

Luego queremos iniciar una instancia de MongoDB por separado sin ninguna otra opción. Asegurándose de que el puerto no entre en conflicto con ninguna otra instancia en ejecución:

 mongod --port 37017 --dbpath data/db 

En un nuevo terminal o ventana de línea de comandos, puede conectarse al shell:

 mongo --port 37017 

Siempre desea al menos una cuenta con privilegios administrativos para al menos “crear cuentas” y modificarlas en caso de que tenga problemas, así que cree una:

 use admin db.createUser( { user: "admin", pwd: "admin", roles: [{ role: "userAdminAnyDatabase", db: "admin" }] } ) 

Ahora salga del shell y cierre la instancia mongod existente que se ejecuta en el otro terminal o símbolo del sistema y luego vuelva a --auth usando --auth :

 mongod --auth --port 37017 --dbpath data/db 

Usuario específico – Asegúrate de seguir estos

Ahora realmente desea crear un usuario que será “utilizado por su aplicación”. Así que estos pasos son importantes para asegurarte de que lo haces bien.

Inicie sesión en un shell utilizando su “usuario administrativo”:

 mongo -u admin -p admin --port 37017 --authenticationDatabase 'admin' 

Alternativamente, puede hacer el método db.auth() como se muestra en la pregunta, pero como se indicó, esto debe estar autorizado en el espacio de nombres "admin" .

Lo siguiente que desea hacer es crear un usuario con acceso a "mydb" como un espacio de nombres con el rol readWrite . Para más información, también vamos a permitir que este usuario tenga readAnyDatabase lo que les permite “listar” todos los espacios de nombres de las bases de datos, si es que no puede hacer nada más con ellos.

IMPORTANTE : Usted crea TODOS sus usuarios en el espacio de nombres "admin" . Y esto será muy importante en futuros lanzamientos:

 use admin db.createUser( { "user": "myuser", "pwd": "password", "roles": [ { "role": "readWrite", "db": "mydb" }, "readAnyDatabase" ] } ) 

Solo para resultados adicionales, echemos un vistazo a los usuarios actuales creados:

 db.getUsers() [ { "_id" : "admin.admin", "user" : "admin", "db" : "admin", "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ] }, { "_id" : "admin.myuser", "user" : "myuser", "db" : "admin", "roles" : [ { "role" : "readWrite", "db" : "mydb" }, { "role" : "readAnyDatabase", "db" : "admin" } ] } ] 

Vea cómo estos se han ampliado en la asignación de nombres y, en particular, los valores asignados a las distintas teclas "db" de cada usuario. Esto debería darle un poco más de información sobre cómo MongoDB busca esto y por qué.

Conexión de Python

Finalmente solo queremos conectarnos desde python. Así que suponiendo que ya tiene Python y Pymongo instalados, es solo una simple lista para verificar:

 import pymongo from pymongo import MongoClient client = MongoClient('mongodb://myuser:password@localhost:37017'); db = client['mydb'] col = db.test col.remove() col.insert_one({ "a": 1 }) for doc in col.find(): print(doc) 

Que muestra el documento creado y listado sin problema:

 {u'a': 1, u'_id': ObjectId('5a08e5e0760108251722a737')} 

Tenga en cuenta que en realidad no necesitamos hacer ninguna mención de "admin" aquí, porque este es el valor predeterminado donde el controlador “espera que las cuentas estén” y donde realmente “debería” estar haciéndolo.

Pero lo hice mal.

Entonces, digamos que originalmente se confundió y creó al usuario bajo "mydb" lugar:

 use mydb db.createUser({ "user": "bert", "pwd": "password", "roles": ["readWrite"] }) 

Si vas a buscar en "admin" ese usuario no está allí. Pero si miras en "mydb" :

 use mydb db.getUsers() [ { "_id" : "mydb.bert", "user" : "bert", "db" : "mydb", "roles" : [ { "role" : "readWrite", "db" : "mydb" } ] } ] 

Así que puedes ver dónde se guardan los datos reales del usuario y cómo se han registrado.

El caso simple aquí es que “debe” decirle a MongoDB de dónde obtener la autenticación para este usuario:

 client = MongoClient('mongodb://bert:password@localhost:37017/mydb'); 

Vea cómo agregamos "mydb" a la cadena de conexión. Así es como se hace.


En realidad, esto está “en progreso” para que sea coherente con TODOS los controladores en la forma en que se realizan las conexiones y dónde se realiza la autenticación, así como en el lugar donde selecciona la base de datos. Pero hay reglas básicas:

  1. Si no se proporciona ningún otro espacio de nombre de la base de datos con detalles de conexión para las credenciales de autenticación, se toma como predeterminado "admin" .

  2. Cuando se proporciona un espacio de nombres de base de datos en la cadena de conexión, se usará para la autenticación y esta es la intención real del espacio de nombres de la base de datos en la cadena de conexión.

  3. Aunque otros controladores “actualmente” difieren en la función del espacio de nombres de la base de datos en la cadena de conexión, el uso se está modificando para que sea coherente con todos los controladores, ya que “usar” un espacio de nombres de la base de datos es en realidad una llamada a la API, en lugar de asignarse desde el Cadena de conexión.

Por lo tanto, el lugar donde se debe autenticar depende de “donde creó el usuario”. Pero realmente debería estar notando que "admin" es el lugar donde “debería” estar haciendo esto en lugar de cualquier otro lugar.

Depredación de la autenticación después de la conexión

Si bien todos los controladores tienen en realidad un método similar al de authenticate() , que se usa de forma muy similar al ejemplo de shell de la pregunta, este método ahora se considera DEPRECADO como se menciona en todo el contenido de la respuesta. sus usuarios en el espacio de nombres "admin" :

“Cambiado en la versión 3.5: En desuso. La autenticación de múltiples usuarios entra en conflicto con el soporte para sesiones lógicas en MongoDB 3.6. Para autenticar como múltiples usuarios, cree múltiples instancias de MongoClient”.

Esta es la razón por la que la respuesta completa aquí se basa en NO usar ese método, ya que está pensado para crear nuevas instancias de conexión o usar la funcionalidad de “sesiones” disponible en MongoDB 3.6.