前言
前面文章中通过客户端工具(MongoDB Shell、Robo 3T)连接 MongoDB 服务时,只要有 IP 地址和端口号,就能连接到数据库,之后就能操作数据库。这是因为默认安装的 MongoDB 没有启用身份验证,也没有设置初始用户名和密码。然而这会导致很多数据安全问题。
MongoDB 提供了多种方式来提高数据库的安全性,例如身份验证、访问控制、加密等。
本文主要介绍 MongoDB 提供的内置角色和权限,然后通过开启身份验证,为用户指定不同的访问权限,来提供数据库的安全性。
前两篇文章,我们分别在 Windows,Linux 和 Docker 中安装了 MongoDB 数据库。本文所介绍的内容,以 Linux 环境中的 MongoDB 为例进行演示。Windows 系统中的操作基本一致。
区分验证和授权
验证即身份验证。用户在连接到 MongoDB 服务时,需要提供用户名,密码和验证数据库进行身份的验证。
授权就是权限控制。做过后台管理系统的小伙伴肯定对 RBAC 模型不陌生。MongoDB 也采用了 RBAC 模型,创建用户时需要为其指定角色,来获取相应的操作数据库的权限。
身份验证只是限制用户能否连接数据库服务,而通过权限控制,就能更精细的控制用户对数据库的各种操作。类比常见的后台管理系统,管理员和普通用户都能登录系统,然后他们能访问的页面、能做的操作却大有不同。
MongoDB 内置角色
MongoDB 通过 RBAC 授予用户对数据和命令的访问权限,并提供了多种内置角色来提供数据库系统中通常需要的不同级别的访问权限。除了使用内置角色,还支持用户创建定义的角色。
这一部分的内容官网有详尽的说明,我们先了解一些常用的角色和权限。
数据库读写角色:
- read:允许用户读取指定数据库
- readWrite:允许用户读写指定数据库
数据库管理员角色:
- dbAdmin:允许用户进行索引创建、删除,查看统计或访问 system.profile,但没有角色和用户管理的权限
- dbOwner:提供对数据库执行任何操作的能力。这个角色组合了 readWrite、dbAdmin 和 userAdmin 角色授权的特权
- userAdmin:提供了在当前数据库中创建和修改角色和用户的能力
所有数据库角色:
- readAnyDatabase:只在 admin 数据库中可用,赋予用户所有数据库的读权限
- readWriteAnyDatabase:只在 admin 数据库中可用,赋予用户所有数据库的读写权限
- userAdminAnyDatabase:只在 admin 数据库中可用,赋予用户所有数据库的 userAdmin 权限
- dbAdminAnyDataBase:只在 admin 数据库中可用,赋予用户所有数据库的 adAdmin 权限
超级用户角色:
- root:只在 admin 数据库中可用,超级用户,拥有超级权限
本文中我们主要用到 root
角色来设置数据库的超级管理员,然后使用 read
和 dbOwner
角色来为某个数据库创建不同权限的用户。
身份验证
开启身份验证
在启动 MongoDB 服务时,通过设置 --auth
在命令行中开启身份验证:
$ mongod -f /data/mongodb/mongodb.conf --auth
或者在配置文件开启 security.authorization
:
security:
authorization: enabled
- authorization:表示是否开启用户访问控制,即客户端是否需要通过用户名和密码验证的方式访问数据库服务。默认为 disabled。
如下,此时 MongoDB 服务已经开启了身份验证:
总结:
开启身份验证:
启动 mongod 服务时,使用 --auth;
使用 mongosh 客户端工具连接到 mongod 服务;
创建一个超级管理员账号;
创建超级管理员用户
MongoDB 开启身份验证后,是没有默认的用户名和密码的,需要自己进行设置。
使用 mongosh
连接服务:
$ mongosh
开启验证后,即使不输入用户名密码也能进入到数据库中,但此时没有权限操作数据库,比如:
此时唯一能做的事情就是创建一个超级管理员角色的用户。
创建超级管理员需要进入 admin
数据库,然后使用 db.createUser
方法创建用户:
use admin;
db.createUser({
user: "Kunwu",
pwd: "abc123",
roles: [
{ role: "root", db: "admin"}
]
});
配置项说明:
- user:创建的用户名。
- pwd:创建的用户密码。
- roles:设置用户角色信息,是一个数组,可以设置多种角色。
- role:设置用户的角色,MongoDB 提供若干种不同的角色,这里设置为超级用户角色
root
。 - db:设置用户权限生效的数据库。由于
root
角色的特殊性,这里只能设置为admin
。但是具备了root
角色的用户,具有超级权限。
使用超级管理员连接服务
开启身份验证后,通过客户端工具(MongoDB Shell、Robo 3T 等)连接到 MongoDB 服务时,需要指定用户名和密码,有两种验证方式。
方式1:连接时验证
在连接数据库服务时指定用户名和认证数据库:
$ mongosh -u Kunwu --authenticationDatabase admin
-
-u/–user:指定用户名
-
–authenticationDatabase:指定认证数据库。认证数据库,就是创建用户时所处的那个数据库。上文创建 Kunwu 时所在的数据库是 admin,所以他的认证数据库就是 admin。
然后命令行中会提示你输入密码:
输入密码后,回车确认即可登录:
也可以直接在命令行通过 -p/--password
来输入密码:
$ mongosh -u Kunwu -p abc123 --authenticationDatabase admin
方式2:连接后验证
先不提供用户名、密码和验证数据库,而是在连接到数据库服务之后,进入认证数据库,使用 db.auth 方法验证用户名和密码。
$ mongosh
验证身份:
use admin;
db.auth('Kunwu', 'abc123');
使用 Robo 3T 连接
创建一个新连接。在 Connection
中输入数据库服务的 IP 和端口:
在第二个 Authentication
中依次输入:
- Database:创建用户时指定的验证数据库
- User Name:用户名
- Password:用户密码
然后点击左下角的测试按钮,进行连接测试:
之后就可以使用 Robo 3T 来管理数据库库了。
关于认证数据库的一点补充
认证数据库,就是指创建用户时所处于的那个数据库。比如前文是在 admin
数据库中创建的超级管理员的用户 Kunwu
,那么此用户的验证数据库就是 admin
。在登录数据库时,authenticationDatabase
就需要指定为 admin
。
验证数据库并不意味着用户只能操作这一个数据库。
MongoDB 中内置了多种角色,创建用户时可以指定多个角色和数据库,此时指定的数据库才是用户能操作的数据库。比如:
db.createUser({
user: "Kunwu",
pwd: "abc123",
roles: [
{ role: "read", db: "db1"},
{ role: "readWrite", db: "db2"},
{ role: "dbOwner", db: "db2"},
]
});
此时,用户 Kunwu
就能操作 db1、db2、db3 这三个数据库,并且具备不同的权限。
所以,结论就是认证数据库并不等同于用户能操作的数据库,这是两个不同的概念。
为应用单独创建用户
超级用户具备最高权限,它适合用来管理其他用户,而不应该用来操作具体的数据库。
我们需要为每一个应用创建单独的用户,来使用数据库服务。比如有一个管理系统 manage
,可以为它创建多个用户,有的只能读取数据,有的可以读写数据,有的具备完全权限等等。
先以超级管理员身份登录到MongoDB中:
$ mongosh -u Kunwu -p abc123 --authenticationDatabase admin
然后为 manage
数据库创建不同的用户:
use manage;
db.create({
user: 'ManageAdmin',
pwd: 'admin123',
roles: [
{ role: "dbOwner", db: 'manage'}
]
});
db.create({
user: 'ManageRead',
pwd: 'user123',
roles: [
{ role: "read", db: 'manage'}
]
})
dbOwner
角色的用户拥有对 manage 数据库执行任何操作的能力。而 read
角色的用户只能从数据库中读取数据。
使用 manage 数据库的管理员用户登录:
$ mongosh -u ManageAdmin -p admin123 --authenticationDatabase manage
使用 manage 数据库的普通用户登录:
$ mongosh -u ManageRead -p user123 --authenticationDatabase manage
总结
到这里,我们简单介绍了 MongoDB 的身份验证和授权的机制。
对于新安装的 MongoDB ,它是没有开启身份验证的。需要进入 admin
数据库,创建一个 root
角色的超级管理员用户。之后再针对具体应用的数据库,使用管理员用户为其创建不同权限的用户,从而做到针对数据库安全的基本保障。
关于角色权限还有很多内容,比如某个角色具体拥有哪些权限,如何创建自定义角色,如何修改用户密码,更新角色等等,大家可以自行访问官网或者查阅其他资料。
感谢阅读!