MongoDB-安全-对User的访问控制

访问控制的基本机制

MongoDB 默认没有启用安全认证和授权。启用后,用户在连接数据库或在进行任何数据库操作之前,需要先提供凭证(用户名、密码)和认证数据库(authentication db)进行身份核实,这就是认证过程。认证通过后,进行任何数据库操作时,会根据用户的角色配置检查用户是否有权限对目标数据执行想要的操作。

主要概念

先来看一个实际的用户:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"_id": "demo.tester",
"user": "tester",
"db": "demo",
"credentials": {
"SCRAM-SHA-1": {
"iterationCount": 10000,
"salt": "iP6HTDUzcTopgTpVOj8lyg==",
"storedKey": "sH9BumOTn+avLaJGKUmLZuKDg/Q=",
"serverKey": "RUdKhVfK4KSmfasl7Anw4re9gis="
}
},
"roles": [{
"role": "read",
"db": "demo"
}]
}

用户是由用户名和认证数据库唯一标示的。”user” 字段是用户名,”db” 字段就是认证数据库,”credentials” 就是密码。

认证数据库就是指在哪个数据库中创建了该用户。上面这个用户的创建过程是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
➜  ~ mongo  # 通过 mongo shell 连接至数据库
MongoDB shell version: 3.0.7
connecting to: test
>
> use demo # 切换至 demo 数据库
switched to db demo
>
> db.createUser({user:"tester", pwd:"hello1234", roles:["read"]})
Successfully added user: { "user" : "tester", "roles" : [ "read" ] }
>
> use admin
switched to db admin
> db.system.users.find()
......(省略了其他用户数据)
{ "_id" : "demo.tester", "user" : "tester", "db" : "demo", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "iP6HTDUzcTopgTpVOj8lyg==", "storedKey" : "sH9BumOTn+avLaJGKUmLZuKDg/Q=", "serverKey" : "RUdKhVfK4KSmfasl7Anw4re9gis=" } }, "roles" : [ { "role" : "read", "db" : "demo" } ] }
>

这个示例先切换至 demo 数据库,再调用 db.createUser 创建了用户,所以该用户的认证数据库就是 demo。

你可以创建用户名完全相同(甚至密码也相同),但是认证数据库不同的用户,它们就是两个不同的用户。所以认证用户身份时,必须提供三项信息:用户名、密码、认证数据库。

认证数据库这个概念就只是用作用户唯一标示的一部分,除此以外没有其他用途。一个认证数据库为 A 的用户也可以对数据库 B, C,D 等有操作权限,只要给它赋予了这些数据库中的相关角色。如果没有为用户配置某个数据库中的角色,即使是认证数据库,用户对该库也没有访问权限。

角色这个概念准确地说是指用户在哪个数据库中拥有什么角色。请看上面的创建用户示例,角色列表中的每一个角色为 { "role" : "xxx", "db" : "xxx" },表示在哪个数据库中拥有什么角色。另一个值得注意的地方是,传给 createUser 的角色列表为 roles:["read"],只指定了角色,木有指定数据库,这种情况下就默认为当前数据库,即认证数据库。

不管你在哪个数据库中创建了用户,用户都被集中保存在 admin 数据库的 system.users 集合中:

1
2
3
4
> use admin
switched to db admin
> db.system.users.find()
......

请求认证用户身份

首先,认证用户身份时必须提供三项信息:用户名、密码、认证数据库。

接着配置数据库服务器开启访问控制,在配置文件(不同平台文件位置很可能不同) /etc/mongod.conf 添加如下信息:

1
2
3
4
5
6
7
security:
# Enable access control
authorization: enabled

# 使用何种认证机制
setParameter:
authenticationMechanisms: SCRAM-SHA-1

有关认证机制,请看 Authentication Mechanisms

在 mongo shell 中请求认证

如果是通过 mongo shell 操作数据库,使用 db.auth("<用户名>", "<密码>") 来请求认证,当前数据库会被用作认证数据库。请看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
➜  ~ mongo  # 通过 mongo shell 连接数据库
MongoDB shell version: 3.0.7
connecting to: test
>
> show dbs # 还未认证,所以没有访问权限
2017-03-06T16:03:41.211+0800 E QUERY Error: listDatabases failed:{
"ok" : 0,
"errmsg" : "not authorized on admin to execute command { listDatabases: 1.0 }",
"code" : 13
}
......
>
> use demo # 切换数据库
switched to db demo
> show collections # 还未认证,所以没有访问权限
2017-03-06T16:03:59.752+0800 E QUERY Error: listCollections failed: {
"ok" : 0,
"errmsg" : "not authorized on demo to execute command { listCollections: 1.0 }",
"code" : 13
}
......
>
> db.auth("tester", "hello1234") # 请求认证身份
1
> show collections # 访问成功
>

编程中通过连接字符串提供认证信息

在实际编程中,通过连接字符串提供认证信息。下面就是标准的 connection URI 方案:

1
mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]

如果指定了用户名、密码就会进行身份认证。[/[database] 就是认证数据库。如果指定了用户凭证,但未指定 database,就将 admin 数据库用作认证数据库。

有关连接字符串的更多信息,请看 Connection String URI Format

参考资源

Connection String URI Format
User Authentication to Database
Enable Authentication
Authentication Mechanisms

0%