Аутентификация после выбора базы данных

#mongodb #authentication #passwords #connection

#python #mongodb #pymongo

Вопрос:

У меня есть 3 базы данных на моем сервере MongoDB. Я использую pymongo для создания некоторых сценариев с Python3.

Я хочу использовать последние версии и методы. Как только я открываю клиент и выбираю базу данных, API для pymongo.MongoClient.[‘mydatabase’].authenticate устарел. https://api.mongodb.com/python/current/api/pymongo/database.html

Аутентификация перед выбором базы данных (при наборе номера клиента), похоже, не стекает к базе данных. Не только для pymongo, но и при использовании оболочки mongo. Итак, у меня такое чувство, что это проблема.

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)
  

Я получаю сообщение об ошибке, что я не авторизован для базы данных. Я знаю, что моя учетная запись работает в оболочке, но я должен сначала набрать номер клиента, затем использовать db, а затем auth.

Вот пример оболочки 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
  

Есть идеи, как я могу выполнить аутентификацию после выбора базы данных или после того, как я использую БД, она запоминает контекст, с которым я набрал?

Комментарии:

1. Цель состоит в том, чтобы ВСЯ аутентификация сохранялась "admin" и просто определяла, в каких пространствах имен базы данных учетная запись имеет доступные привилегии. Таким образом, вы бы назначили привилегии пользователю для "mydb" , но нет такого требования, чтобы вы «входили» только в эту базу данных. Это просто означает, что если вы переключитесь на "foo" пространство имен базы данных, где нет назначенных привилегий, то вы «ничего не сможете сделать». Если у вас были привилегии для «обоих» пространств имен базы данных, то вам разрешен доступ к вещам без необходимости повторной «аутентификации». Это несколько понятнее?

2. Сначала я думал, что так оно и работает. Например, без использования базы данных я создал своего пользователя mongo со всеми привилегиями администратора буквально со всеми возможными правами доступа и другого пользователя только с доступом на чтение. Затем я бы авторизовался (все еще в admin) с этой основной учетной записью. Затем переключитесь и используйте «mydb», и когда я «показываю пользователям» в mydb, ничего не отображается. Итак, я подумал, что мне нужно воссоздать учетную запись в mydb и предоставить доступ.

3. Есть ли что-то в предоставленном ответе, что, по вашему мнению, не отвечает на ваш вопрос? Если это так, пожалуйста, прокомментируйте ответ, чтобы уточнить, что именно необходимо решить, чего нет. Если он действительно отвечает на заданный вами вопрос, пожалуйста, обратите внимание, чтобы принять ваши ответы на вопросы, которые вы задаете

4. Это так. Для меня это имеет смысл, потому что именно так я ожидал, что это сработает в первый раз, и я понял, что создал отдельных пользователей в одной базе данных. Однако, когда я пытаюсь создать нового пользователя, admin я все еще не могу использовать d.auth() для входа в базу данных, которую я использую. (На данный момент я использую только shell, так как понял, что проблема никогда не была в pymongo). Я полагаю, что мне, возможно, придется переустановить mongo и начать чистую, поскольку я продолжаю возиться с пользователями, конфигурацией и т. Д.

5. Вам предоставляется чистый случай, который показывает запуск чистой базы данных и воспроизводимые шаги для того, чтобы вы могли запускать и реплицировать и видеть, каков правильный процесс. Как только вы сможете увидеть, каков правильный процесс, и в ответе указано, что на самом деле было задано, тогда процесс здесь заключается в том, чтобы «принять ответ» , чтобы указать его правильность другим, просматривающим вопрос и его ответ.

Ответ №1:

Похоже, вам здесь не хватает некоторых понятий, поэтому я в основном отвечу как «руководство» к тому, что вы должны делать вместо этого. Таким образом, «аутентификация» — это на самом деле не то, что вы делаете «после» подключения, а скорее вам нужно «искать в нужном месте», когда вы на самом деле пытаетесь пройти аутентификацию.

Мы можем начать это, по существу следуя процессу, описанному в Enable Auth из основной документации, но специально измененному, потому что вы хотите запускать этот «тест» под своей собственной учетной записью пользователя и в локальном каталоге.

Этапы пересмотра — прямо из документации

Итак, сначала хотелось бы выбрать локальный рабочий каталог и указать путь для файлов хранилища базы данных под ним. В системах на основе * nix вы можете сделать что-то вроде:

 mkdir -p scratch/data/db
cd scratch
  

Затем мы хотим запустить отдельный экземпляр MongoDB без каких-либо других опций. Убедитесь, что порт не конфликтует с любым другим запущенным экземпляром:

 mongod --port 37017 --dbpath data/db
  

Затем в новом окне терминала или командной строки вы можете подключиться к оболочке:

 mongo --port 37017
  

Вы всегда хотите, чтобы хотя бы одна учетная запись с правами администратора хотя бы «создавала учетные записи» и изменяла их на случай возникновения проблем, поэтому создайте ее:

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

Теперь выйдите из командной оболочки и закройте существующий mongod экземпляр, запущенный в другом терминале или командной строке, а затем запустите его снова, используя --auth :

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

Конкретный пользователь — убедитесь, что вы следуете этим

Теперь вы действительно хотите создать пользователя, который будет «использоваться вашим приложением». Итак, эти шаги важны, чтобы убедиться, что вы все поняли правильно.

Войдите в оболочку, используя своего «администратора»:

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

Вы можете поочередно выполнить db.auth() метод, как показано в вопросе, но, как уже отмечалось, это должно быть разрешено в "admin" пространстве имен.

Следующее, что вы хотите сделать, это создать пользователя с доступом к "mydb" как к пространству имен с readWrite ролью. Для пинки мы также собираемся предоставить этому пользователю readAnyDatabase возможность «перечислять» все пространства имен баз данных, если на самом деле они не могут ничего с ними делать.

ВАЖНО: вы создаете ВСЕХ своих пользователей в "admin" пространстве имен. И это будет очень важно в будущих выпусках:

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

Просто для дополнительного вывода давайте посмотрим на текущих созданных пользователей:

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

Посмотрите, как они расширились в именовании, и, в частности, значения, присвоенные различным "db" ключам для каждого пользователя. Это должно дать вам немного больше информации о том, как MongoDB ищет это и почему.

Подключение к Python

Наконец, мы просто хотим подключиться из python. Итак, предполагая, что у вас уже установлены python и pymongo, тогда это просто простой список для проверки:

 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)
  

Который показывает документ, созданный и перечисленный без проблем:

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

Обратите внимание, что нам на самом деле не нужно "admin" здесь ничего упоминать, потому что это значение по умолчанию, в котором драйвер «ожидает, что учетные записи будут», и где вы действительно «должны» это делать.

Но я сделал это неправильно

Итак, допустим, вы изначально запутались и "mydb" вместо этого создали пользователя:

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

Если вы посмотрите, "admin" этого пользователя там нет. Но если вы посмотрите на "mydb" :

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

Таким образом, вы можете видеть, где теперь хранятся фактические пользовательские данные и как они были записаны.

Простой случай здесь заключается в том, что вы «должны» сообщить MongoDB, где получить аутентификацию для этого пользователя:

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

Посмотрите, как мы добавляем "mydb" к строке подключения. Вот как это делается.


На самом деле это «выполняется», чтобы быть согласованным со ВСЕМИ драйверами в том, как устанавливаются соединения и где происходит аутентификация, а также где вы выбираете базу данных. Но есть основные правила:

  1. Если никакое другое пространство имен базы данных не содержит сведений о подключении для учетных данных аутентификации, то "admin" по умолчанию используется значение then .

  2. Если в строке подключения указано пространство имен базы данных, оно будет использоваться для аутентификации, и это фактическое назначение пространства имен базы данных в строке подключения.

  3. Хотя другие драйверы «в настоящее время» отличаются ролью пространства имен базы данных в строке подключения, использование изменяется, чтобы соответствовать всем драйверам, которые «используют» пространство имен базы данных, на самом деле является вызовом API, а не назначается из строки подключения.

Итак, где вам нужно пройти аутентификацию, зависит от того, «где вы создали пользователя». Но вы действительно должны отметить, что "admin" это то место, где вы «должны» делать это, а не где-либо еще.

Устаревание аутентификации после подключения

Хотя все драйверы на самом деле имеют метод authenticate() , аналогичный, который используется так же, как пример оболочки в вопросе, этот метод теперь считается УСТАРЕВШИМ, как упоминается во всем содержании ответа, «предполагается», что вы фактически храните своих пользователей в "admin" пространстве имен:

«Изменено в версии 3.5: устарело. Аутентификация нескольких пользователей противоречит поддержке логических сеансов в MongoDB 3.6. Для аутентификации в качестве нескольких пользователей создайте несколько экземпляров MongoClient «.

Вот почему весь ответ здесь основан на ТОМ, чтобы НЕ использовать этот метод, поскольку вы предназначены для создания новых экземпляров соединения, или вместо этого использовать функциональность «сеансов», доступную из MongoDB 3.6.