Python 选择数据库后进行身份验证

Python 选择数据库后进行身份验证,python,mongodb,pymongo,Python,Mongodb,Pymongo,我的MongoDB服务器中有3个数据库。我正在使用pymongo对Python3编写脚本 我想使用最新的版本和实践。打开客户端并选择数据库后,pymongo.MongoClient.['mydatabase'].authenticate的API将被弃用。 选择数据库之前的身份验证(在拨打客户机时)似乎不会流向数据库。不仅仅是pymongo,我使用MongoShell时也是如此。所以我觉得这就是问题所在 script.py import pymongo from pymongo import M

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

我想使用最新的版本和实践。打开客户端并选择数据库后,pymongo.MongoClient.['mydatabase'].authenticate的API将被弃用。

选择数据库之前的身份验证(在拨打客户机时)似乎不会流向数据库。不仅仅是pymongo,我使用MongoShell时也是如此。所以我觉得这就是问题所在

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,然后再进行身份验证

下面是一个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

你知道我可以在选择数据库后进行身份验证,还是在使用数据库时它会记住我拨打的上下文吗?

这里你似乎缺少一些概念,所以我基本上会作为你应该做什么的“指南”来回答。所以“身份验证”实际上并不是在“连接”之后进行的,而是在实际尝试身份验证时需要“寻找正确的位置”

我们可以从基本上遵循核心文档中概述的流程开始,但由于您希望在自己的用户帐户和本地目录下运行此“测试”,因此特别进行了更改

修订步骤-直接来自文档 因此,首先需要选择一个本地工作目录,并为该目录下的数据库存储文件创建一个路径。在基于*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" }]
  }
)
现在退出shell并关闭在另一个终端或命令提示符下运行的现有
mongod
实例,然后使用
--auth
再次启动它:

mongod --auth --port 37017 --dbpath data/db
特定用户-请确保遵循以下步骤 现在,您实际上想要创建一个“由您的应用程序使用”的用户。因此,这些步骤对于确保正确操作非常重要

使用“管理用户”登录shell:

您可以交替执行问题中所示的
db.auth()
方法,但如前所述,此必须在
“admin”
命名空间上获得授权

接下来要做的是创建一个用户,该用户可以访问
“mydb”
,作为具有
readWrite
角色的名称空间。对于kicks,我们还将让该用户拥有
readAnyDatabase
,允许他们“列出”所有数据库名称空间,如果他们实际上无法对其执行任何其他操作的话

重要:在
的“admin”
命名空间中创建所有用户。这在以后的版本中非常重要:

为了获得更多输出,让我们看看当前创建的用户:

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”

因此,您可以看到实际用户数据现在保存在何处以及如何记录

这里的简单情况是,您“必须”告诉MongoDB从何处获取此用户的身份验证:

client = MongoClient('mongodb://bert:password@localhost:37017/mydb');
请参见如何将“mydb”添加到连接字符串中。这是如何完成的


这实际上是“正在进行”的,以便在如何建立连接、在何处进行身份验证以及在何处选择数据库方面与所有驱动程序保持一致。但有一些基本规则:

  • 如果没有其他数据库名称空间提供身份验证凭据的连接详细信息,则
    将“admin”
    视为默认值

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

  • 尽管其他驱动程序“目前”在连接字符串上的数据库名称空间的角色不同,但使用方法正在更改,以与“使用”数据库名称空间实际上是API调用的所有驱动程序一致,而不是从连接字符串分配

  • 因此,您需要在何处进行身份验证取决于“您在何处创建了用户”。但您应该注意的是,
    “admin”
    是您“应该”进行身份验证的地方,而不是其他任何地方

    连接后不推荐使用身份验证 虽然所有驱动程序实际上都有一个与类似的方法,该方法的使用与问题中的shell示例非常类似,但现在认为此方法已被弃用,正如答案的整个内容所述,您“打算”将用户实际存储在
    的“admin”
    命名空间中:

    “在版本3.5中更改:已弃用。验证多个用户与支持l冲突
    use mydb
    db.createUser({ "user": "bert", "pwd": "password", "roles": ["readWrite"] })
    
    use mydb
    db.getUsers()
    [
            {
                    "_id" : "mydb.bert",
                    "user" : "bert",
                    "db" : "mydb",
                    "roles" : [
                            {
                                    "role" : "readWrite",
                                    "db" : "mydb"
                            }
                    ]
            }
    ]
    
    client = MongoClient('mongodb://bert:password@localhost:37017/mydb');