分享到

简介

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

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

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

先决条件

要跟随本指南操作,您需要在具有适当权限的MongoDB 服务器上拥有一个账户。

我们将使用的命令和方法

要在 MongoDB 中创建、修改和删除用户以及配置身份验证,您需要以下核心方法:

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

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

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

所需权限

要执行上述命令,您需要使用具有多种不同权限操作的账户登录到 MongoDB。您所需的具体权限取决于您需要使用的命令。

要获取其他用户的信息,您当前的用户必须启用以下权限操作:

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

要更改用户的密码或账户详情,您可能需要以下权限:

本指南不涉及角色管理,因此不需要 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

举例来说,我们可以通过更改 authenticationRestrictions 字段,更新对 admin 数据库进行身份验证的 tom 账户,使其只能从托管服务器本身的同一台计算机登录。

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 参数设置为 true

基本语法如下所示:

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

Justin Ellingwood

Justin 自 2013 年以来一直撰写有关数据库、Linux、基础设施和开发者工具的文章。他目前与妻子和两只兔子住在柏林。他通常不需要用第三人称写作,这让所有相关方都松了一口气。
© . All rights reserved.