一、前言
在默认情况下,mongod是监听在127.0.0.1之上的,任何客户端都可以直接连接27017,默认是 【非授权模式】 (也就是不需要任何权限验证、不需要验证账户,直接在命令窗口中输入 mongo 回车,就可以进行相关操作),这是非常不安全的(尤其是在生产环境中,当然如果是自己玩玩的话就无所谓了)。MongoDB使用的是基于角色的访问控制(Role-Based Access Control,RBAC)来管理用户对实例的访问。通过对用户授予一个或多个角色来控制用户访问数据库资源的权限和数据库操作的权限,在对用户分配角色之前,用户无法访问实例。本文主要介绍MongoDB RBAC(Role-Based Access Control)权限管理机制,其核心是给每个用户赋予一定的权限,用户连接MongoDB 前需先验证,验证通过后即拥有用户的权限,权限决定了用户在某一组资源(如某个DB、某个特定集合)上可以执行哪些操作(比如增删改查、建索引)。
二、RBAC权限模型简介
RBAC(基于角色的访问控制):英文名称Role-Based Access Control,介绍这种模型的权限系统设计。取消了用户和权限的直接关联,改为通过用户关联角色、角色关联权限的方法来间接地赋予用户权限。从而实现了解耦。RBAC在发展过程中分为以下几个版本。RBAC0、RBAC1、RBAC2、RBAC3。
- RBAC0:这是RBAC的初始形态,也是最原始、最简单的RBAC版本;
- RBAC1:基于RBAC0的优化,增加了角色的分层(即:子角色),子角色可以继承父角色的所有权限;
- RBAC2:基于RBAC0的另一种优化,增加了对角色的一些限制:角色互斥、角色容量等;
- RBAC3: 最复杂也是最全面的RBAC模型,它在RBAC0的基础上,将RBAC1和RBAC2中的优化部分进行了整合;
模型中有几个关键的术语:
- 用户(User):系统接口及访问的操作者,即登录的用户本身,有一个用户ID(定义uuid)
- 角色(Role):具有一类相同操作权限的用户的总称,即这个用户拥有几个身份,一个用户可以有几个角色
- 权限(Access):能够访问某接口或者做某操作的授权资格,Access英语中的含义是访问,引申为访问的资源,习惯上可以称之为权限
三、MongoDB系统角色(RBAC)
MongoDB内部提供了一系列内置的角色,这些角色是为了完成一些基本的数据库操作。每个内置角色提供了用户在角色数据库内数据库级别所有非系统类集合的访问权限,也提供了对集合级别所有系统集合的访问权限。MongoDB在每个数据库上都提供内置的数据库用户角色和数据库管理角色,但只在admin数据库中提供其它的内置角色。
3.1 用户
MongoDB是基于角色的访问控制,所以创建用户需要指定用户的角色,在创建用户之前需要满足:
- 先在admin数据库中创建角色为userAdmin或userAdminAnyDatabase的用户作为管理用户的用户;
- 启用访问控制,进行登录用户验证,这样创建用户才有意义。
3.1.1 创建用户管理的用户 启用访问控制登录之前,首先需要在admin数据库中创建角色为userAdmin或userAdminAnyDatabase作为用户管理的用户,之后才能通过这个用户创建其它角色的用户,这个用户作为其它所有用户的管理者。
3.2 角色
在MongoDB中通过角色对用户授予相应数据库资源的操作权限,每个角色当中的权限可以显式指定,也可以通过继承其他角色的权限,或者两都都存在的权限。
3.2.1 MongoDB内置角色
- 数据库用户角色:read、readWrite;
- 数据库管理角色:dbAdmin、dbOwner、userAdmin;
- 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;
- 备份恢复角色:backup、restore;
- 所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
- 超级用户角色:root
- 内部角色:__system
角色 | 权限描述 |
read | 可以读取指定数据库中任何数据。 |
readWrite | 可以读写指定数据库中任何数据,包括创建、重命名、删除集合。 |
readAnyDatabase | 可以读取所有数据库中任何数据(除了数据库config和local之外)。 |
readWriteAnyDatabase | 可以读写所有数据库中任何数据(除了数据库config和local之外)。 |
dbAdmin | 可以读取指定数据库以及对数据库进行清理、修改、压缩、获取统计信息、执行检查等操作。 |
dbAdminAnyDatabase | 可以读取任何数据库以及对数据库进行清理、修改、压缩、获取统计信息、执行检查等操作(除了数据库config和local之外)。 |
clusterAdmin | 可以对整个集群或数据库系统进行管理操作。 |
userAdmin | 可以在指定数据库创建和修改用户。 |
userAdminAnyDatabase | 可以在指定数据库创建和修改用户(除了数据库config和local之外)。 |
3.2.1.1 数据库用户角色
- read
read角色包含读取所有非系统集合数据和订阅部分系统集合(system.indexes、system.js、system.namespaces)的权限。
该角色权限包含命令操作:changeStream、collStats、dbHash、dbStats、find、killCursors、listIndexes、listCollections。
- readWrite
readWrite角色包含read角色的权限同时增加了对非系统集合数据的修改权限,但只对系统集合system.js有修改权限。
该角色权限包含命令操作:collStats、convertToCapped、createCollection、dbHash、dbStats、dropCollection、createIndex、dropIndex、find、insert、killCursors、listIndexes、listCollections、remove、renameCollectionSameDB、update。
3.2.1.2 数据库管理角色
- dbAdmin
dbAdmin角色包含执行某些管理任务(与schema相关、索引、收集统计信息)的权限,该角色不包含用户和角色管理的权限。
对于系统集合(system.indexes、system.namespaces、system.profile)包含命令操作:collStats、dbHash、dbStats、find、killCursors、listIndexes、listCollections、dropCollection and createCollection(仅适用system.profile)
对于非系统集合包含命令操作:bypassDocumentValidation、collMod、collStats、compact、convertToCapped、createCollection、createIndex、dbStats、dropCollection、dropDatabase、dropIndex、enableProfiler、reIndex、renameCollectionSameDB、repairDatabase、storageDetails、validate
- dbOwner
dbOwner角色包含对数据所有的管理操作权限。即包含角色readWrite、dbAdmin和userAdmin的权限。
- userAdmin
userAdmin角色包含对当前数据库创建和修改角色和用户的权限。该角色允许向其它任何用户(包括自身)授予任何权限,所以这个角色也提供间接对超级用户(root)的访问权限,如果限定在admin数据中,也包括集群管理的权限。
该角色权限包含命令操作:changeCustomData、changePassword、createRole、createUser、dropRole、dropUser、grantRole、revokeRole、setAuthenticationRestriction、viewRole、viewUser。
3.2.1.3 集群管理角色
- clusterManager
clusterManager角色包含对集群监控和管理操作的权限。拥有此角色的用户能够访问集群中的config数据库和local数据库。
对于整个集群该角色包含命令操作:addShard、appendOplogNote、applicationMessage、cleanupOrphaned、flushRouterConfig、listSessions (3.6新增)、listShards、removeShard、replSetConfigure、replSetGetConfig、replSetGetStatus、replSetStateChange、resync。
对于集群中所有的数据库包含命令操作:enableSharding、moveChunk、splitChunk、splitVector。
对于集群中config数据库和local数据库包含的命令操作可以参考官方文档:docs.mongodb.com/manual/refe…
- clusterMonitor
clusterMonitor角色包含针对监控工具具有只读操作的权限。如工具MongoDB Cloud Manager和工具Ops Manager。
对于整个集群该角色包含命令操作:checkFreeMonitoringStatus(4.0新增)、connPoolStats、getCmdLineOpts、getLog、getParameter、getShardMap、hostInfo、inprog、listDatabases、listSessions (3.6新增)、listShards、netstat、replSetGetConfig、replSetGetStatus、serverStatus、setFreeMonitoring (4.0新增)、shardingState、top。
对于集群中所有的数据为包含命令操作:collStats、dbStats、getShardVersion、indexStats、useUUID(3.6新增)。
对于集群中config数据库和local数据库包含的命令操作可以参考官方文档:docs.mongodb.com/manual/refe…
- hostManager
hostManager角色包含针对数据库服务器的监控和管理操作权限。
对于整个集群该角色包含命令操作:applicationMessage、closeAllDatabases、connPoolSync、cpuProfiler、flushRouterConfig、fsync、invalidateUserCache、killAnyCursor (4.0新增)、killAnySession (3.6新增)、killop、logRotate、resync、setParameter、shutdown、touch、unlock。
对于集群中所有的数据库包含命令操作:killCursors、repairDatabase。
- clusterAdmin
clusterAdmin角色包含MongoDB集群管理最高的操作权限。该角色包含clusterManager、clusterMonitor和hostManager三个角色的所有权限,并且还拥有dropDatabase操作命令的权限。
3.2.1.4 备份恢复角色
- backup
backup角色包含备份MongoDB数据最小的权限。
对于MongoDB中所有的数据库资源包含命令操作:listDatabases、listCollections、listIndexes。
对于整个集群包含命令操作:appendOplogNote、getParameter、listDatabases。
对于以下数据库资源提供find操作权限:
- 对于集群中的所有非系统集合,包括自身的config数据库和local数据库;
- 对于集群中的系统集合:system.indexes、system.namespaces、system.js和system.profile;
- admin数据库中的集合:admin.system.users和admin.system.roles;
- config.settings集合;
- 2.6版本之前的system.users集合。
对于config.setting集合还有insert和update操作权限。
- restore
restore角色包含从备份文件中还原恢复MongoDB数据(除了system.profile集合)的权限。
restore角色有以下注意事项:
- 如果备份中包含system.profile集合而恢复目标数据库没有system.profile集合,mongorestore会尝试重建该集合。因此执行用户需要有额外针对system.profile集合的createCollection和convertToCapped操作权限;
- 如果执行mongorestore命令时指定选项--oplogReplay,则restore角色包含的权限无法进行重放oplog。如果需要进行重放oplog,则需要只对执行mongorestore的用户授予包含对实例中任何资源具有任何权限的自定义角色。
对于整个集群包含命令操作:getParameter。
对于所有非系统集合包含命令操作:bypassDocumentValidation、changeCustomData、changePassword、collMod、convertToCapped、createCollection、createIndex、createRole、createUser、dropCollection、dropRole、dropUser、grantRole、insert、revokeRole、viewRole、viewUser。
关于restore角色包含其它的命令操作可以参考官方文档:docs.mongodb.com/manual/refe…
3.2.1.5 所有数据库角色
以下角色只存在于admin数据库,并且适用于除了config和local之外所有的数据库。
- readAnyDatabase
readAnyDatabase角色包含对除了config和local之外所有数据库的只读权限。同时对于整个集群包含listDatabases命令操作。
在MongoDB3.4版本之前,该角色包含对config和local数据库的读取权限。当前版本如果需要对这两个数据库进行读取,则需要在admin数据库授予用户对这两个数据库的read角色。
- readWriteAnyDatabase
readWriteAnyDatabase角色包含对除了config和local之外所有数据库的读写权限。同时对于整个集群包含listDatabases命令操作。
在MongoDB3.4版本之前,该角色包含对config和local数据库的读写权限。当前版本如果需要对这两个数据库进行读写,则需要在admin数据库授予用户对这两个数据库的readWrite角色。
- userAdminAnyDatabase
userAdminAnyDatabase角色包含类似于userAdmin角色对于所有数据库的用户管理权限,除了config数据库和local数据库。
对于集群包含命令操作:authSchemaUpgrade、invalidateUserCache、listDatabases。
对于系统集合admin.system.users和admin.system.roles包含命令操作:collStats、dbHash、dbStats、find、killCursors、planCacheRead、createIndex、dropIndex。
该角色不会限制用户授予权限的操作,因此,拥有角色的用户也有可能授予超过角色范围内的权限给自己或其它用户,也可以使自己成为超级用户,userAdminAnyDatabase角色也可以认为是MongoDB中的超级用户角色。
- dbAdminAnyDatabase
dbAdminAnyDatabase角色包含类似于dbAdmin角色对于所有数据库管理权限,除了config数据库和local数据库。同时对于整个集群包含listDatabases命令操作。
在MongoDB3.4版本之前,该角色包含对config和local数据库的管理权限。当前版本如果需要对这两个数据库进行管理,则需要在admin数据库授予用户对这两个数据库的dbAdmin角色。
3.2.1.6 超级用户角色
以下角色包含在任何数据库授予任何用户任何权限的权限。这意味着用户如果有以下角色之一可以为自己在任何数据库授予任何权限。
- dbOwner角色(作用范围为admin数据库)
- userAdmin角色(作用范围为admin数据库)
- userAdminAnyDatabase角色
以下角色包含数据库所有资源的所有操作权限。
- root
root角色包含角色readWriteAnyDatabase、dbAdminAnyDatabase、userAdminAnyDatabase、clusterAdmin、restore和backup联合之后所有的权限。
3.2.1.7 内部角色
- __system
MongoDB将此角色授予代表集群成员的用户对象,如副本集(replica set)成员或mongos实例。该角色允许用户对于需要的数据库操作都具有相应的权限,不要将该角色授予应用程序用户或其它管理员用户。
3.2.2 用户自定义角色
虽然MongoDB提供了一系列内置角色,但有时内置角色所包含的权限并不满足所有需求,所以MongoDB也提供了创建自定义角色的方法。当创建一个自定义角色时需要进入指定数据库进行操作,因为MongoDB通过数据库和角色名称对角色进行唯一标识。
除了在admin数据库中创建的角色之外,在其它数据库中创建的自定义角色包含的权限只适用于角色所在的数据库,并且只能继承同数据库其它角色的权限。在admin数据库中创建的自定义角色则不受此限制。
MongoDB将所有的角色信息存储在admin数据库的system.roles集合中,不建议直接访问此集合内容,而是通过角色管理命令来查看和编辑自定义角色。
3.3 权限
权限由指定的数据库资源(resource)以及允许在指定资源上进行的操作(action)组成。
- 资源(resource)包括:数据库、集合、部分集合和集群;
- 操作(action)包括:对资源进行的增、删、改、查(CRUD)操作。
在角色定义时可以包含一个或多个已存在的角色,新创建的角色会继承包含的角色所有的权限。在同一个数据库中,新创建角色可以继承其他角色的权限,在admin数据库中创建的角色可以继承在其它任意数据库中角色的权限。
关于角色权限的查看,可以通过如下命令查询:
// 进入mongo指令平台 mongo // 查询当前数据库中的角色权限 > db.runCommand({ rolesInfo: "<rolename>" }) // 查询其它数据库中指定的角色权限 > db.runCommand({ rolesInfo: { role: "<rolename>", db: "<database>" } } // 查询多个角色权限 > db.runCommand( { rolesInfo: [ "<rolename>", { role: "<rolename>", db: "<database>" }, ... ] } ) // 查询所有角色权限(仅用户自定义角色) > db.runCommand({ rolesInfo: 1 }) // 查询所有角色权限(包含内置角色) > db.runCommand({ rolesInfo: 1, showBuiltinRoles: true })
四、账号密码设置
MongoDB密码和传统数据如mysql等有些区别:MongoDB的用户名和密码是基于特定数据库的,而不是基于整个系统的。所有所有数据库DB都需要设置密码。
4.1 创建所有数据库的管理角色
4.1.1 查看所有数据库
管理员身份运行cmd.exe,先cd到Mongodb安装目录的bin目录, 使用mongo.exe进入MongoDB的命令行管理界面。
- 进入mongo指令界面
// 进入mongo命令行管理界面 $ mongo
- 查看所有数据库
// 查看所有数据库(在MongoDB新版本里并没有admin数据库,但是并不妨碍第2步操作。) $ show dbs
- 查询结果显示
> show dbs admin 0.000GB config 0.000GB local 0.000GB
4.1.2 进入admin数据库
- 进入admin数据库
// 进入admin数据库 $ use admin
- 结果显示
> use admin switched to db admin
4.1.3 创建管理员账户
MongoDB中的用户是基于身份role的,该管理员账户的 role是 userAdminAnyDatabase。admin用户用于管理账号,不能进行关闭数据库等操作。
- 进入
kuaizhidao
数据库
// 添加管理员用户(用户名:admin 和 密码:admin 是可以自定义的 【但是要记牢哦!!】) db.createUser({ user:"admin", // 账户 pwd:"admin", // 密码 roles: [{ role: "userAdminAnyDatabase", // 角色userAdminAnyDatabase db: "admin" // 数据库名 }] })
- 创建成功结果显示
Successfully added user: { "user" : "admin", "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ] }
- 设置完成,可以输入
show users
或者db.getUsers()
查看是否设置成功。
// 查看当前库下的用户 > show users { "_id" : "admin.admin", "userId" : UUID("a245d242-6ce6-4239-a77d-4318038b46b0"), "user" : "admin", "db" : "admin", "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ], "mechanisms" : [ "SCRAM-SHA-1", "SCRAM-SHA-256" ] }
4.1.4 超级管理员root
现在我们为MongoDB的admin数据库添加一个用户root超级管理员,角色:root,密码也是root,MongoDB可以为每个数据库都建立权限认证,也就是你可以指定某个用户可以登录到哪个数据库。root角色用于关闭数据库db.shutdownServer()
,在MongoDB中admin数据库是一个特别的数据库,这个数据库的用户,可以访问MongoDB中的所有数据库。
- 添加超级管理员用户
db.createUser({ user: "root", pwd: "root", roles: [ { role: "root", db: "admin" } ] })
- 创建成功结果显示
Successfully added user: { "user" : "root", "roles" : [ { "role" : "root", "db" : "admin" } ] }
- 设置完成,可以输入
show users
或者db.getUsers()
查看是否设置成功。
// 查看当前库下的用户 { "_id" : "admin.admin", "userId" : UUID("a245d242-6ce6-4239-a77d-4318038b46b0"), "user" : "admin", "db" : "admin", "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ], "mechanisms" : [ "SCRAM-SHA-1", "SCRAM-SHA-256" ] } { "_id" : "admin.root", "userId" : UUID("2e178964-7b97-4502-b013-b0db87755758"), "user" : "root", "db" : "admin", "roles" : [ { "role" : "root", "db" : "admin" } ], "mechanisms" : [ "SCRAM-SHA-1", "SCRAM-SHA-256" ] }
4.2 创建单个数据库的管理角色
我们除了可以设置数据库的超级管理员以外,还可以给每个数据库设置单独的管理员。其只有操作单独数据的一定权限。这里我们以 kuaizhidao
数据库为例,给kuaizhidao
配置一个账户。
注:各个不同的数据库之间,可以创建有一个 或 多个账户,各数据库之间账户、密码都是独立的,不能互相访问!
4.2.1 查看所有数据库
管理员身份运行cmd.exe,先cd到Mongodb安装目录的bin目录, 使用mongo.exe进入MongoDB的命令行管理界面。
- 进入mongo指令界面
// 进入mongo命令行管理界面 $ mongo
- 查看所有数据库
// 查看所有数据库(在MongoDB新版本里并没有admin数据库,但是并不妨碍第2步操作。) $ show dbs
- 查询结果显示
> show dbs admin 0.000GB config 0.000GB kuaizhidao 0.000GB local 0.000GB
4.2.2 进入yourdatabase数据库
- 进入yourdatabase数据库kuaizhidao
// 进入yourdatabase数据库 $ use kuaizhidao
- 结果显示
> use kuaizhidao switched to db kuaizhidao
4.2.3 创建账号
现在我们为MongoDB的kuaizhidao数据库添加一个用户kauizhidao管理员,角色:role: "dbOwner"代表数据库所有者角色,拥有最高该数据库最高权限,密码也是kuaizhidao,比如新建索引等当账号管理员和超级管理员,可以为自己的数据库创建用户了。(坑)这时候一定,一定要切换到所在数据库上去创建用户,不然创建的用户还是属于admin。
如果是读写角色的话,权限设置为role: "readWrite"
- 创建数据库用户
// 给kuaizhidao数据库 创建一个名为:kuaizhidao的账户,角色为:dbOwner db.createUser({ user:"kuaizhidao", // 用户名 pwd: "kuaizhidao", // 密码 roles: [{ role: "dbOwner", // 角色 db: "kuaizhidao" // 数据库名 }] })
注意:如果不给admin表设置账号,则就算给业务表设置账号密码也没用,没有账号密码一样可以访问。
- 创建成功显示结果
Successfully added user: { "user" : "kuaizhidao", "roles" : [ { "role" : "dbOwner", "db" : "kuaizhidao" } ] }
- 设置完成,可以输入
show users
或者db.getUsers()
查看是否设置成功。
// 查看当前库下的用户 { "_id" : "kuaizhidao.kuaizhidao", "userId" : UUID("9670ee67-011d-4036-a78d-5523026a196d"), "user" : "kuaizhidao", "db" : "kuaizhidao", "roles" : [ { "role" : "dbOwner", "db" : "kuaizhidao" } ], "mechanisms" : [ "SCRAM-SHA-1", "SCRAM-SHA-256" ] }
4.3 数据库用户操作
删除用户必须由账号管理员来删,所以,切换到admin角色
$ use admin db.auth("root","root")
4.3.1 删除用户
- 删除单个用户
// 删除单个用户 db.system.users.remove({user:"XXXXXX"})
// 删除用户 db.dropUser('admin')
- 删除所有用户
// 删除所有用户 db.system.users.remove({})
4.3.2 修改用户密码
// 修改用户密码 db.updateUser('admin', {pwd: 'root'})
4.3.3 密码认证
// 密码认证 db.auth('root', 'root')
4.4 开启验证
开启验证可以通过--auth参数或者配置文件mongod.cfg
中的security: authorization: enabled
设置开启。
4.4.1 修改配置文件
找到 MongoDB 安装目录,找到bin文件夹,打开 mongod.cfg文件,找到以下配置:
#security:
修改为:
#security: security: authorization: enabled
4.4.2 重启 MongoDB
$ net start MongoDB
五、 常用命令
5.1 以系统管理员身份运行powershell
Win+R
5.2 链接数据库 mongo
$ mongo MongoDB shell version v4.4.6 connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("e5c1430e-0b85-4c6b-82e1-d63f16f6a10d") } MongoDB server version: 4.4.6 --- The server generated these startup warnings when booting: 2021-05-13T13:12:11.023+08:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted ---
5.3 查看数据库 show dbs
5.4 切换到admin数据库,use admin
5.5 创建超级管理员账号 db.createUser()
例子: db.createUser({user:'root',pwd:'root',roles:['root']})
其中:user:后面接用户名,pwd接密码,roles是创建的用户角色
5.6 切换到blog 数据 use blog(blog是我自己创建的数据库)
5.7 创建普通账号 db.createUser()
例子:db.createUser({user:'carrie',pwd:'carrie',roles:['readWrite']}) 之后就直接退出
5.8 卸载Mongodb服务
1.停止服务 net stop mongodb
2.mongod --romove
5.9 创建mongodb服务
例子:mongod --logpath="C:\Program Files\MongoDB\Server\4.2\log\mongod.log" --dbpath="C:\Program Files\MongoDB\Server\4.2\data" --install --auth
其中mongod --logpath=是指定输出日志存储目录
--dbpath=是指定数据库存储目录
--install --auth 意味着必须是管理员身份才能操作数据
5.10 启用mongodb服务 net start mongodb
5.11 在项目中使用账号链接数据库
mongoose.connect('mongodb://user:password@localhost:port/database') 例子: // 引入mongoose第三方模块 const mongoose = require('mongoose'); // 连接数据库 mongoose.connect( 'mongodb://carrie:carrie@localhost:27017/kuaizhidao', { useNewUrlParser: true, useUnifiedTopology: true }) .then(() => console.log('数据库连接成功')) .catch(() => console.log('数据库连接失败'))