分享至

简介

管理用户和 身份验证 是管理 MongoDB 服务器最重要的管理任务之一。您必须确保服务器配置为能够正确识别您的用户和应用程序,并拒绝无法正确身份验证的连接或操作。

为了管理这些需求,您必须能够决定服务器需要的用户,并创建这些帐户。在此过程中,您可以设置身份验证详细信息以允许使用新身份进行外部访问。

在本指南中,我们将逐步介绍如何创建、查看和删除用户帐户。我们将介绍如何为您的帐户设置身份验证,以及如何在需要更改用户密码时更新凭据。

先决条件

要按照本指南进行操作,您需要在具有适当权限的 MongoDB 服务器上拥有一个帐户。

我们将使用的命令和方法

为了在 MongoDB 中创建、修改和删除用户并配置身份验证,您需要的核心方法是

  • db.createUser:创建一个新的 MongoDB 用户帐户
  • db.updateUser:更新用户帐户的详细信息
  • db.changeUserPassword:更改用户帐户使用的密码
  • db.dropUser:删除 MongoDB 用户帐户

此外,以下数据库命令对于查找系统上的用户信息很有用

  • db.runCommand('usersInfo'):显示有关一个或多个 MongoDB 用户帐户的信息

所需权限

要执行以上命令,您需要使用具有许多不同 权限操作 的帐户登录 MongoDB。您需要的特定权限取决于您需要使用的命令。

要获取有关其他用户的 info,您的当前用户必须启用以下权限操作

要创建新用户,您的当前用户必须启用以下权限操作

要更改用户的密码或帐户详细信息,您可能需要以下权限

在本指南中,我们将不会介绍角色管理,因此 grantRolerevokeRole 权限操作将不需要。

要删除用户帐户,您的当前用户必须启用以下权限操作

了解 MongoDB 如何实现用户和身份验证

在我们开始创建和管理帐户之前,了解 MongoDB 如何定义和存储此信息会很有帮助。

在 MongoDB 中,用户帐户是帐户用户名与特定身份验证数据库的组合。身份验证数据库只是定义用户的数据库,并不意味着对范围或权限的限制。身份验证数据库是用于管理其他数据的普通数据库,而不是特殊的专用数据库。

用户帐户名称在其身份验证数据库中必须是唯一的。但是,同一个用户名可以在不同的身份验证数据库中重复使用以创建新的、不同的用户帐户。

由于这种设计,只有包含用户名和认证数据库才能准确识别帐户。要对帐户进行身份验证,还需要提供与帐户关联的凭据。这通常是密码,但也可以是证书。

如何创建用户?

现在我们已经了解了 MongoDB 如何对用户帐户进行概念化,我们可以讨论如何创建新用户。请记住,要登录您的 MongoDB 服务器,需要使用具有相应权限的用户才能继续操作。

要创建新用户,您必须先切换到要作为新用户认证数据库的数据库。

首先,您可以通过输入以下内容来获取系统上已配置的数据库列表

show dbs
admin 0.000GB
config 0.000GB
local 0.000GB

使用 use 命令切换到用户将与之关联的数据库

use admin
switched to db admin

要创建新用户,可以使用 db.createUser() 方法,也可以使用 createUser 数据库命令。无论哪种方式,您都需要在 user 对象中传递用户名(user 字段)、密码(pwd 字段)和用户应添加到的角色数组(roles 键)。

要使用 db.createUser() 方法创建名为 tom 的新用户,密码设置为 hellothere,角色数组为空,可以输入

db.createUser({
user: "tom",
pwd: "hellothere",
roles: []
})
Successfully added user: { "user" : "tom", "roles" : [ ] }

使用 createUser 数据库命令的相同操作将如下所示

db.runCommand({
createUser: "tom",
pwd: "hellothere",
roles: []
})
Successfully added user: { "user" : "tom", "roles" : [ ] }

这两个不同的选项非常相似,因此我们只会在适用的情况下显示数据库方法。但是,如果您更喜欢数据库命令语法,可以在 MongoDB 命令参考文档 中找到每个关联的命令。

在上面的命令中,我们明确地在 user 对象中定义了内联密码。为了防止密码被记录和检索,您也可以在 user 文档中使用 passwordPrompt() 方法,以便 MongoDB 在运行命令时交互式地提示您输入密码。密码将不可见,因此您的命令历史记录将保持干净

db.createUser({
user: "tom",
pwd: passwordPrompt(),
roles: []
})
Enter password:
Successfully added user: { "user" : "tom", "roles" : [ ] }

请记住,如果您没有启用 TLS/SSL,密码仍将以明文形式发送到服务器。

如何显示现有用户?

接下来,让我们看看如何查找有关现有用户的更多信息。

要返回多个用户,可以在 db.getUsers() 方法上使用它来显示当前数据库中的所有用户。首先,切换到您有兴趣查询的数据库

use admin

接下来,使用 db.getUsers() 方法返回与当前数据库关联的所有用户

db.getUsers()
[
{
"_id" : "admin.root",
"userId" : UUID("f5ded238-19c9-4886-b649-711ec36993cb"),
"user" : "root",
"db" : "admin",
"roles" : [
{
"role" : "root",
"db" : "admin"
}
],
"mechanisms" : [
"SCRAM-SHA-1",
"SCRAM-SHA-256"
]
},
{
"_id" : "admin.tom",
"userId" : UUID("e7a0abde-a9f9-412a-bfd5-eb11fda41fd3"),
"user" : "tom",
"db" : "admin",
"roles" : [ ],
"mechanisms" : [
"SCRAM-SHA-1",
"SCRAM-SHA-256"
]
}
]

要另外显示每个用户的凭据信息,请将一个带有 showCredentials 键设置为 true 的对象传递给该方法

use admin
db.getUsers({
showCredentials: true
})
[
{
"_id" : "admin.root",
. . .
"credentials" : {
"SCRAM-SHA-1" : {
"iterationCount" : 10000,
"salt" : "WpB0H4f7dG8XlCDyaVzarA==",
"storedKey" : "b11nA1+mGo3+Tr8P//u3NEdJLHk=",
"serverKey" : "3xE8o663hjqySrMCQcXjSxmjmhk="
},
"SCRAM-SHA-256" : {
"iterationCount" : 15000,
"salt" : "UtsfNRedf2ek5tbWFoGs2g52U0H7Na44wV4rYA==",
"storedKey" : "mz9/qHnI79pNAIQm0MZTKZ0U3qFk0xhUDd2grvKtMdI=",
"serverKey" : "c/sA4j+I/29Ea1y07zxoMcBgHFoYTUAa6luX3Z9sToQ="
}
},
. . .
},
{
"_id" : "admin.tom",
. . .
"credentials" : {
"SCRAM-SHA-1" : {
"iterationCount" : 10000,
"salt" : "qCbxWQSGt3QoN3S1aM5AEg==",
"storedKey" : "hypim5+m2wqbS1gc47o2itc7jew=",
"serverKey" : "h9myNoSvY2015yqvw3UldmJzZCg="
},
"SCRAM-SHA-256" : {
"iterationCount" : 15000,
"salt" : "lNtIVL79J8FF+uPaFfRMwPK079gfLEUrsQe3Qg==",
"storedKey" : "u8pgn3OJiZxIwEL7ryZkoAF5bnMefQEEsZDTXNDCTRY=",
"serverKey" : "BmmfVeikSA0DN1aZmyZP9NXi5owxGr1ZRmVX2XH8qVg="
}
},
. . .
}
]

要查询与特定条件匹配的用户,可以传递一个定义 filter 键来定义匹配条件的对象。

例如,要获取当前数据库中所有具有 root 角色的用户的信息,可以输入

use admin
db.getUsers({
filter: {
"roles.role": "root"
}
})
[
{
"_id" : "admin.root",
"userId" : UUID("f5ded238-19c9-4886-b649-711ec36993cb"),
"user" : "root",
"db" : "admin",
"roles" : [
{
"role" : "root",
"db" : "admin"
}
],
"mechanisms" : [
"SCRAM-SHA-1",
"SCRAM-SHA-256"
]
}
]

要获取特定用户,可以使用 db.getUser() 方法。这与 db.getUsers() 方法类似,但返回单个用户。您传递给方法的不是对象,而是一个包含您要检索的用户名字符串

use admin
db.getUser("tom")
{
"_id" : "admin.tom",
"userId" : UUID("e7a0abde-a9f9-412a-bfd5-eb11fda41fd3"),
"user" : "tom",
"db" : "admin",
"roles" : [ ],
"mechanisms" : [
"SCRAM-SHA-1",
"SCRAM-SHA-256"
]
}

您可以选择包含额外的 args 对象,通过将以下键设置为 true 来指定您想要的其他信息

  • showCredentials:除了常规输出之外,还显示凭据信息
  • showPrivileges:除了常规输出之外,还显示权限信息
  • showAuthenticationRestrictions:除了常规输出之外,还显示帐户上的身份验证限制

例如,您可以告诉 MongoDB 通过输入以下内容为您提供所有上述信息

use admin
db.getUser("tom",
{
showCredentials: true,
showPrivileges: true,
showAuthenticationRestrictions: true
})
{
"_id" : "admin.tom",
"userId" : UUID("e7a0abde-a9f9-412a-bfd5-eb11fda41fd3"),
"user" : "tom",
"db" : "admin",
"mechanisms" : [
"SCRAM-SHA-1",
"SCRAM-SHA-256"
],
"credentials" : {
"SCRAM-SHA-1" : {
"iterationCount" : 10000,
"salt" : "qCbxWQSGt3QoN3S1aM5AEg==",
"storedKey" : "hypim5+m2wqbS1gc47o2itc7jew=",
"serverKey" : "h9myNoSvY2015yqvw3UldmJzZCg="
},
"SCRAM-SHA-256" : {
"iterationCount" : 15000,
"salt" : "lNtIVL79J8FF+uPaFfRMwPK079gfLEUrsQe3Qg==",
"storedKey" : "u8pgn3OJiZxIwEL7ryZkoAF5bnMefQEEsZDTXNDCTRY=",
"serverKey" : "BmmfVeikSA0DN1aZmyZP9NXi5owxGr1ZRmVX2XH8qVg="
}
},
"roles" : [ ],
"inheritedRoles" : [ ],
"inheritedPrivileges" : [ ],
"inheritedAuthenticationRestrictions" : [ ],
"authenticationRestrictions" : [ ]
}

如何更改 MongoDB 用户的密码?

要更改用户的密码,可以使用 db.changeUserPassword() 方法。同样,您必须在执行命令之前切换到用户的身份验证数据库。

db.changeUserPassword() 方法需要两个参数:要更改的帐户的用户名和帐户的新密码。

例如,要将使用 admin 数据库进行身份验证的用户 tom 的密码更改为 secretpassword,可以输入

use admin
db.changeUserPassword("tom", "secretpassword")

db.createUser() 方法一样,您也可以使用 passwordPrompt() 方法作为第二个参数,而不是提供内联密码。当执行命令时,MongoDB 会提示您输入密码

use admin
db.changeUserPassword("tom", passwordPrompt())
Enter password:

如何更改其他用户帐户详细信息?

要更改与用户帐户关联的其他信息,可以使用 db.updateUser() 方法。在更新用户详细信息之前,请确保切换到用户的身份验证数据库。

db.updateUser() 方法要求您指定用户名,然后提供包含要更新的数据的对象。您选择更新的任何字段都将被新信息完全替换,因此请确保在对象中包含原始数据以及新数据,如果您只希望追加新信息。

您在命令中包含的包含更改信息的物体可以包含许多不同的字段。让我们回顾一下它们

  • customData:与用户帐户关联的任何任意数据。
  • roles:授予用户的角色。通常最好使用 db.grantRolesToUser()db.revokeRolesFromUser() 方法来控制角色成员资格,而不是使用此键进行更新,因为您可以单独追加和删除角色。
  • pwd:用户的密码。如果只需要更新该字段,则通常使用 db.ChangeUserPassword() 方法更容易。
  • authenticationRestrictions:指定帐户的限制,这些限制可以限制用户可以连接到的 IP 地址。此键的值是定义 clientSource 和/或 serverAddress 的对象或数组,其中包含指定有效 IP 地址或范围的数组。在 MongoDB 文档中了解更多关于 身份验证限制 的信息。
  • mechanisms:用于凭据的特定身份验证机制。可以设置为 SCRAM-SHA-1SCRAM-SHA-256 中的一个或两个,但如果当前没有提供新密码,则只能更改为当前机制的子集。
  • passwordDigestor:指定哪个组件处理用户的密码。可以是 server(默认)或 client

例如,我们可以更新针对 admin 数据库进行身份验证的 tom 帐户,使其只能从托管服务器本身的同一台计算机登录,方法是更改 authenticationRestrictions 字段

use admin
db.updateUser("tom", {
authenticationRestrictions: [ {
clientSource: ["127.0.0.1", "::1"],
serverAddress: ["127.0.0.1", "::1"]
} ]
})

现在,如果您要求 MongoDB 向您显示有关用户的相关信息,它将显示帐户的额外限制

use admin
db.getUser("tom", {
showAuthenticationRestrictions: true
})
{
"_id" : "admin.tom",
"userId" : UUID("e7a0abde-a9f9-412a-bfd5-eb11fda41fd3"),
"user" : "tom",
"db" : "admin",
"mechanisms" : [
"SCRAM-SHA-1",
"SCRAM-SHA-256"
],
"roles" : [ ],
"authenticationRestrictions" : [
{
"clientSource" : [
"127.0.0.1",
"::1"
],
"serverAddress" : [
"127.0.0.1",
"::1"
]
}
],
"inheritedRoles" : [ ],
"inheritedPrivileges" : [ ],
"inheritedAuthenticationRestrictions" : [ ]
}

要撤销这些限制,我们可以使用空数组再次运行命令

use admin
db.changeUser("tom", {
authenticationRestrictions: []
})

如何删除 MongoDB 用户?

要删除 MongoDB 用户帐户,可以使用 db.dropUser() 方法。在删除用户之前,请确保连接到用户的身份验证数据库。

要执行 db.dropUser() 方法,您需要提供要删除的用户的名称

db.dropUser("tom")

成功删除后,MongoDB 将返回 true

true

如果帐户在当前数据库中不存在,它将返回 false

结论

MongoDB 的用户管理和身份验证配置允许您控制谁可以连接到您的服务器以及他们的用户属性是什么。在下一篇文章中,我们将讨论如何通过解决用户管理的授权部分来限制用户具有的访问级别。

常见问题解答

要列出 MongoDB 中的现有用户,可以使用 db.getUsers() 方法来显示当前数据库中的所有用户。

语法将如下所示

use admin
db.getUsers()

有关 db.getUsers() 的更多详细信息。

为了在 MongoDB 中创建 数据库管理员用户,您需要在 admin 数据库中使用 db.createUser() 方法。

以下演示了用于创建数据库管理员的语法。

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

要删除 MongoDB 用户,您可以使用 db.dropUser() 方法。这需要在 admin 数据库中完成,语法如下

use admin
db.dropUser("tom")

要获取 MongoDB 中所有现有用户的列表,您可以使用 db.getUsers() 方法。

基本语法如下

use admin
db.getUsers()

要查询 特定用户,您可以使用 db.getUser() 方法,并将 showPrivileges arg 设置为 true

基本语法如下

use admin
db.getUser("tom",
{
showPrivileges: true,
})
关于作者
Justin Ellingwood

Justin Ellingwood

Justin 自 2013 年以来一直在撰写有关数据库、Linux、基础设施和开发人员工具的文章。他目前与妻子和两只兔子住在柏林。他通常不必以第三人称写作,这对所有相关方来说都是一种解脱。