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

标签 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时。所以我觉得这就是问题所在。
脚本.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,然后再进行身份验证。
下面是一个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

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

最佳答案

你似乎遗漏了一些概念,所以我基本上会回答你应该做什么。所以“身份验证”并不是在“连接”之后才做的事情,而是在实际尝试身份验证时需要“寻找正确的位置”。
我们可以从基本上遵循核心文档中Enable Auth中概述的过程开始,但由于您希望在自己的用户帐户和本地目录下运行此“测试”,因此需要进行特别修改。
修订步骤-直接从文档
因此,首先需要选择一个本地工作目录,并在该目录下为数据库存储文件创建一个路径。在基于*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角色的命名空间。对于kicks,我们还将让这个用户拥有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"那个用户不在那里。但如果你看一下
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"添加到连接字符串。就是这样做的。
这实际上是“进行中”的,与所有驱动程序的连接方式、进行身份验证的位置以及选择数据库的位置一致。但有一些基本规则:
如果没有为其他数据库命名空间提供用于身份验证凭据的连接详细信息,则默认为"mydb"
如果在连接字符串上提供了数据库命名空间,则此命名空间将用于身份验证,这是数据库命名空间在连接字符串上的实际意图。
尽管其他驱动程序“当前”在连接字符串上的数据库名称空间的角色不同,但其用法将被更改为与“使用”数据库名称空间实际上是api调用而不是从连接字符串分配的所有驱动程序一致。
因此,您需要在哪里进行身份验证取决于“您在哪里创建了用户”。但你应该注意到"admin"是你“应该”做这件事的地方,而不是其他地方。
连接后不推荐使用身份验证
虽然所有驱动程序实际上都有一个类似于"admin"的方法,该方法的用法与问题中的shell示例非常相似,但现在该方法被认为是不推荐的,正如在答案的整个内容中所提到的,它是“有意”将用户实际存储在authenticate()命名空间中:
“在版本3.5中更改:已弃用。对多个用户的身份验证与MongoDB 3.6中对逻辑会话的支持冲突。要作为多个用户进行身份验证,请创建mongoclient的多个实例。”
这就是为什么这里的全部答案都是基于不使用该方法,因为您打算创建新的连接实例,或者使用MongoDB 3.6提供的“会话”功能。

关于python - 挑选数据库后进行身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47253584/

相关文章:

python - 如何使用批量操作更新mongodb中的文档?

node.js - 更新 MongoDb 子文档中数组中的特定文档

javascript - MongoDB MapReduce,仅当 count > 1 时返回

linux - 类型错误 : __init__() got an unexpected keyword argument 'timeout' pymongo

python - 如何在 Flask 中为每个请求创建 pymongo 连接

node.js - 使用docker连接nodejs和mongo

python - 为什么在 Python 解释器中使用模数时会出现段错误?

python - 在 Mac OS X 中设置 Tkinter Python 应用程序图标

c++ - 编写虚拟网络摄像头?

python - 将字符串拆分为空白列表,当下一个字符不是破折号时不包括单个空格