挑选数据库后进行身份验证

时间:2017-11-12 20:27:29

标签: python mongodb pymongo

我的MongoDB服务器中有3个数据库。我正在使用pymongo用Python3编写脚本。

我想使用最新版本和做法。一旦我打开客户端并选择数据库,就不推荐使用pymongo.MongoClient。['mydatabase']。authenticate的API。 https://api.mongodb.com/python/current/api/pymongo/database.html

选择数据库之前的身份验证(在拨打客户端时)似乎没有流向数据库。不只是对于pymongo,还有我使用mongo shell时。所以我觉得这就是问题所在。

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)

我收到的错误是我未获得数据库授权。我知道我的帐户在shell中运行但我必须首先拨打客户端然后使用db然后使用auth。

这是一个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

我知道如何在选择数据库后进行身份验证,或者一旦我使用数据库,它会记住我拨打的上下文?

1 个答案:

答案 0 :(得分:1)

你似乎在这里遗漏了一些概念,所以我基本上会回答作为"指南"到了你应该做的事情。所以"身份验证'并不是你做的事情"之后"连接,但你需要"寻找合适的地方"当你真正尝试进行身份验证时。

我们可以从核心文档中基本上遵循Enable Auth中概述的过程开始,但是因为你想要运行这个" test"在您自己的用户帐户和本地目录下。

修订步骤 - 直接从文档

首先,我们希望选择一个本地工作目录,并为其下的数据库存储文件创建一个路径。在基于* nix的系统上,您可以执行以下操作:

mkdir -p scratch/data/db
cd scratch

然后我们想要启动一个单独的MongoDB实例而不需要任何其他选项。确保端口不与任何其他正在运行的实例冲突:

mongod --port 37017 --dbpath data/db

在新的终端或命令行窗口中,您可以连接到shell:

mongo --port 37017

您始终希望至少有一个具有管理权限的帐户至少可以创建帐户"如果你遇到麻烦就改变它们,所以创建一个:

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

现在退出shell并关闭在另一个终端或命令提示符下运行的现有mongod实例,然后使用--auth重新启动它:

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

特定用户 - 请确保遵循这些

现在,您实际上想要创建一个将由您的应用程序使用的用户"。因此,这些步骤对于确保您正确行事非常重要。

使用"管理员用户":

登录shell
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"将被视为默认

  2. 如果连接字符串上提供了数据库命名空间,将用于身份验证,这是连接字符串上数据库命名空间的实际意图。

  3. 虽然其他司机"目前"数据库名称空间在连接字符串上的作用不同,使用情况正在改变,以便与使用"使用"的所有驱动程序保持一致。数据库名称空间实际上是一个API调用,而不是从连接字符串中分配。

  4. 因此,您需要进行身份验证的位置取决于"您创建用户的位置"。但是你应该注意"admin"是你应该"应该"这样做而不是其他任何地方。

      

    连接后验证的弃用

         

    虽然所有驱动程序实际上都有类似于authenticate()的方法,这与问题中的shell示例非常相似,但此方法现在被视为 DEPRECATED ,正如整篇内容所述答案是"意图"您实际将用户存储在"admin"命名空间中:

         

    "在版本3.5中更改:已弃用。认证多个用户冲突,支持MongoDB 3.6中的逻辑会话。要以多个用户身份进行身份验证,请创建MongoClient的多个实例。"

         

    这就是为什么这里的整个答案基于 NOT 使用该方法,因为您要创建新的连接实例,或者使用"会话" MongoDB 3.6提供的功能。