MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Autenticar depois de escolher o banco de dados


Você parece estar perdendo alguns conceitos aqui, então basicamente responderei como um "guia" para o que você deve fazer. Portanto, "autenticação" não é realmente algo que você faz "após" a conexão, mas você precisa estar "procurando no lugar certo" quando realmente tentar autenticar.

Podemos começar seguindo basicamente o processo descrito em Ativar autenticação da documentação principal, mas alterado especificamente porque você deseja executar este "teste" em sua própria conta de usuário e diretório local.

Etapas de revisão - diretamente da documentação


Então, primeiro gostaria de escolher um diretório de trabalho local e criar um caminho para os arquivos de armazenamento do banco de dados abaixo dele. Em sistemas baseados em *nix, você pode fazer algo como:
mkdir -p scratch/data/db
cd scratch

Em seguida, queremos iniciar uma instância separada do MongoDB sem outras opções. Certificando-se de que a porta não está em conflito com nenhuma outra instância em execução:
mongod --port 37017 --dbpath data/db

Em um novo terminal ou janela de linha de comando, você pode se conectar ao shell:
mongo --port 37017

Você sempre quer pelo menos uma conta com privilégios administrativos para pelo menos "criar contas" e alterá-las caso tenha problemas, então crie uma:
use admin
db.createUser(
  {
    user: "admin",
    pwd: "admin",
    roles: [{ role: "userAdminAnyDatabase", db: "admin" }]
  }
)

Agora saia do shell e feche o mongod existente instância em execução no outro terminal ou prompt de comando e, em seguida, inicie-a novamente usando --auth :
mongod --auth --port 37017 --dbpath data/db

Usuário específico - Certifique-se de seguir estes


Agora você realmente deseja criar um usuário que será "usado pelo seu aplicativo". Portanto, essas etapas são importantes para garantir que você acerte.

Faça login em um shell usando seu "usuário administrativo":
mongo -u admin -p admin --port 37017 --authenticationDatabase 'admin'

Você pode alternadamente fazer o db.auth() como mostrado na pergunta, mas conforme observado, deve ser autorizado no "admin" namespace.

A próxima coisa que você quer fazer é criar um usuário com acesso a "mydb" como um namespace com o readWrite Função. Por diversão, também vamos permitir que este usuário tenha o readAnyDatabase permitindo que eles "listem" todos os namespaces de bancos de dados, se não puderem fazer qualquer outra coisa com eles.
use admin
db.createUser(
  {
    "user": "myuser",
    "pwd": "password",
    "roles": [
      { "role": "readWrite", "db": "mydb" },
      "readAnyDatabase"
    ]
  }
)

Apenas para saída adicional, vamos ver os usuários criados atualmente:
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"
                        }
                ]
        }
]

Veja como eles se expandiram na nomenclatura e, particularmente, os valores atribuídos aos vários "db" teclas de cada usuário. Isso deve fornecer um pouco mais de visão sobre como o MongoDB pesquisa isso e por quê.

Conexão Python


Finalmente, queremos apenas conectar a partir de python. Então, supondo que você já tenha python e pymongo instalados, é apenas uma lista simples para verificar:
import pymongo
from pymongo import MongoClient
client = MongoClient('mongodb://myuser:[email protected]:37017');

db = client['mydb']
col = db.test

col.remove()

col.insert_one({ "a": 1 })

for doc in col.find():
  print(doc)

Que mostra o documento criado e listado sem problemas:
{u'a': 1, u'_id': ObjectId('5a08e5e0760108251722a737')}

Observe que não precisamos fazer nenhuma menção a "admin" aqui, porque este é o padrão onde o driver "espera que as contas estejam" e onde você realmente "deveria" estar fazendo isso.

Mas eu fiz do jeito errado


Então, digamos que você originalmente ficou confuso e criou o usuário em "mydb" em vez de:
use mydb
db.createUser({ "user": "bert", "pwd": "password", "roles": ["readWrite"] })

Se você for olhar em "admin" esse usuário não está lá. Mas se você olhar em "mydb" :
use mydb
db.getUsers()
[
        {
                "_id" : "mydb.bert",
                "user" : "bert",
                "db" : "mydb",
                "roles" : [
                        {
                                "role" : "readWrite",
                                "db" : "mydb"
                        }
                ]
        }
]

Assim, você pode ver onde os dados reais do usuário agora são mantidos e como foram registrados.

O caso simples aqui é que você "deve" informar ao MongoDB de onde obter a autenticação para este usuário:
client = MongoClient('mongodb://bert:[email protected]:37017/mydb');

Veja como adicionamos "mydb" para a cadeia de conexão. Assim que se faz.

Na verdade, isso está "em andamento" para ser consistente com TODOS os drivers em como as conexões são feitas e onde a autenticação acontece, bem como onde você seleciona o banco de dados. Mas existem regras básicas:

  1. Se nenhum outro namespace de banco de dados for fornecido com detalhes de conexão para credenciais de autenticação, "admin" é considerado o padrão .

  2. Onde houver um namespace de banco de dados fornecido na string de conexão, isso será usado para autenticação e esta é a intenção real do namespace do banco de dados na cadeia de conexão.

  3. Embora outros drivers "atualmente" difiram na função do namespace do banco de dados na string de conexão, o uso está sendo alterado para ser consistente com todos os drivers que "usar" um namespace do banco de dados é de fato uma chamada de API, em vez de ser atribuído a partir do cadeia de conexão.

Portanto, onde você precisa autenticar depende de "onde você criou o usuário". Mas você realmente deve estar notando que "admin" é o lugar onde você "deveria" estar fazendo isso em vez de qualquer outro lugar.