python mongodb pymongo

python - Autenticar después de elegir la base de datos



mongodb pymongo (1)

Tengo 3 bases de datos en mi servidor MongoDB. Estoy usando pymongo para hacer algunas secuencias de comandos con Python3.

Quiero usar las últimas versiones y prácticas. Una vez que abro el cliente y elijo 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 al cliente y luego usar db y luego auth.

Aquí hay un ejemplo de mongo shell:

$ 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 autenticar después de elegir la base de datos o una vez que uso el DB recuerda el contexto con el que marqué?


Parece que le faltan algunos conceptos aquí, así que básicamente responderé como una "guía" de lo que debería hacer en su lugar. Entonces, "autenticación" no es realmente algo que haces "después de" la conexión, sino que debes estar "buscando en el lugar correcto" cuando realmente intentas autenticarte.

Podemos comenzar esto 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 desde la documentación

Entonces, primero querría elegir un directorio de trabajo local y crear una ruta para los archivos de almacenamiento de la base de datos debajo de eso. En los sistemas basados ​​en * nix puede hacer algo como:

mkdir -p scratch/data/db cd scratch

Luego, queremos iniciar una instancia de MongoDB separada sin ninguna otra opción. Asegúrese de que el puerto no entre en conflicto con ninguna otra instancia en ejecución:

mongod --port 37017 --dbpath data/db

En una nueva ventana de terminal o línea de comando, 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úrese de seguir estos

Ahora realmente desea crear un usuario que será "utilizado por su aplicación". Por lo tanto, estos pasos son importantes para garantizar que lo haga bien.

Inicie sesión en un shell con su "usuario administrador":

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 señaló, 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 las patadas, también vamos a permitir que este usuario tenga la readAnyDatabase permite "enumerar" todos los espacios de nombres de bases de datos, si no puede hacer otra cosa con ellos.

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

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

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

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 se han expandido en la asignación de nombres, y en particular los valores asignados a las diferentes teclas "db" en cada usuario. Esto debería darle un poco más de información sobre cómo MongoDB busca esto y por qué.

Conexión Python

Finalmente solo queremos conectarnos desde python. Entonces, suponiendo que ya haya instalado Python y Pymongo, entonces es solo una lista simple 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 estén las cuentas" y donde realmente "debería" hacerlo.

Pero lo hice mal

Entonces, supongamos que originalmente se confundió y creó el usuario en "mydb" :

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" } ] } ]

Para que pueda 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 cómo se realizan las conexiones y dónde se realiza la autenticación, así como donde selecciona la base de datos. Pero hay reglas básicas:

  1. Si no se proporciona ningún otro espacio de nombres de la base de datos con detalles de conexión para las credenciales de autenticación, se considera que "admin" es el predeterminado .

  2. Cuando hay un espacio de nombres de la base de datos proporcionado 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 que "usar" un espacio de nombres de la base de datos es en realidad una llamada API, en lugar de ser asignado desde el Cadena de conexión.

Entonces, dónde necesita autenticarse depende de "dónde creó el usuario". Pero realmente deberías notar que "admin" es el lugar donde "deberías" estar haciendo esto en lugar de en cualquier otro lugar.

Desaprobación de autenticación después de conectar

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

"Modificado 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 autenticarse como múltiples usuarios, cree múltiples instancias de MongoClient".

Esta es la razón por la cual toda la respuesta aquí se basa en NO usar ese método, ya que está destinado a crear nuevas instancias de conexión, o usar la funcionalidad de "sesiones" disponible en MongoDB 3.6.