MongoDB用户验证和权限管理
官方参考页面:
https://docs.mongodb.com/v3.6/tutorial/enable-authentication/
https://docs.mongodb.com/v3.6/tutorial/enforce-keyfile-access-control-in-existing-replica-set/
前言:
前些年很多用户对mongodb的安全意识是很淡漠的,也因此在前几年出现了一些很严重的针对mongodb的攻击。
本文以mongodb3.6为例,介绍mongodb目前的用户验证机制,当然用户验证只是mongodb安全体系的一部分,更加全面的安全内容参考:https://docs.mongodb.com/v3.6/security/
虽然mongodb提供了一系列的加强安全的措施,但实际上经常会用到的也就是用户验证(本文称为client auth)和集群成员间的验证(本文称为internal auth)了,internal auth多使用keyfile,关于keyfile验证参考上述的第二个官方链接即可,这种keyfile是集群节点间的一种权限验证机制,是mongo实例级别的,会在最后介绍下。
关于加密算法:
1.集群成员间的internal authentication加密方式有keyfiles和x.509两种,前者较多见,后者涉及TLS/SSL封装,我没用过。
2.用户验证的加密算法在4.0之前默认为SCRAM,4.0之后MONGODB-CR(3.0前的默认加密方式)已被废弃,而x.509不但支持internal auth也支持client auth,但是很少使用。
本文主要介绍最核心的用户验证,这种用户验证的粒度是库级别的。
一、如何创建用户?
安装MongoDB后auth认证默认是关闭的,此时admin库是不可见的(旧版本不可见,新版本里只是admin下的用户相关的system.users不可见),现创建一个超级帐号:
use admin
//查看当前库内已有用户
show users
//查看当前库内可用的roles,默认只有built-in roles
show roles
//创建用户,roles可以使用当前库内的角色,或者其他库内的角色
db.createUser({user: "root",pwd: "root",roles: [ { role: "root", db: "admin" } ]})
//如何修改密码
db.changeUserPassword('root','rootNew');
//已有用户新增和解除built-in roles
db.grantRolesToUser('<username>', [{ role: '<built-in role>', db: 'admin' }])
db.revokeRolesFromUser( "<username>", [{ role: '<built-in role>', db: 'admin' }])
//删除用户命令如下,虽然所有库的用户信息全存在admin的system.users中,删用户时还是要use <库名>才能删除
use db_name
db.dropUser("<username>")
创建用户时需要牢记的几点:
- 创建用户必须指定库名,即用户是和库绑定的。即便是超级用户的创建也是如此,如果你创建root用户时是在业务库里,那你以后登录root也只能指定业务库的库名了(超级账户一般建于admin库下)。
- 创建用户时指定的built-in roles也是与库绑定的,指定的哪个库的角色,就拥有哪个库的操作权限,即在test库内创建db.createUser({user: "test",pwd: "test",roles: [ { role: "read", db: "test1" } ]})只能读test1下的collection不能读test下的。
- 不同的库下可以存在相同的用户名,即admin.root用户和test.root用户是可以同时存在的。
- 登陆mongo shell时如果不指定库名,默认登入的test库(只在3.6验证过,其他版本自行验证),你需要use db_name后才能进行db.auth(),当然你可以选择直接mongo db_name -u username -p password登陆。
- 一般来说创建一个root角色的超级用户root即可(或一个__system权限的system用户),创建一些普通权限的用户做日常操作。
示例,创建包含多个角色的用户:
use test
db.createUser(
{
user: "myTester",
pwd: "xyz123",
roles: [ { role: "readWrite", db: "test" },
{ role: "read", db: "reporting" } ]
}
)
//这里第二个role是reporting.read,说明此用户拥有reporting下的读权限。
use admin
db.createUser(
{
user: "myUserAdmin",
pwd: "abc123",
roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" ]
}
)
//未指定db的role默认是使用当前库下的角色的,这里其实readWriteAnyDatabase相当于{ role: "readWriteAnyDatabase", db: "admin" }
二、什么是角色(roles)?
https://docs.mongodb.com/manual/reference/built-in-roles/index.html
roles即一系列权限的集合,系统内置了一系列的built-in roles以便可以方便的为用户授权,一般来说使用这些built-in roles创建用户就可以了,除非你需要更细粒度的指定权限(那你可能需要下点功夫看官网文档)。
Built-In Roles简略介绍(详细介绍参考以上官方链接):
Database User Roles:
read
提供本库下所有非系统collection的读权限,以及少数几个系统collection的读权限,例如system.indexes, system.js, and system.namespaces
readWrite
提供本库下所有非系统collection的读写权限,以及系统collection system.js的读写权限。
Database Administration Roles:
dbAdmin
提供一些库管理的权限,诸如索引创建,增删集合,删库等等,并没有对所有集合的读权限,因此其实很少会用到。
userAdmin
提供在本库下创建用户、角色,删除用户、角色,修改密码等一系列用户相关的权限。
dbOwner
库拥有者权限,即readWrite、dbAdmin、userAdmin角色的合体。
Cluster Administration Roles:
clusterAdmin
集群管理权限,clusterManager、clusterMonitor、hostManager角色的合体,此外再加上dropDatabase权限。
clusterManager
集群管理者权限,提供诸如添加shard,删除shard,修改副本集配置等权限。
clusterMonitor
集群监控权限,顾名思义拥有查看一系列集群状态的权限。
hostManager
参考官网链接的解释,很少使用。
Backup and Restoration Roles:
backup
即进行数据备份的权限,实例级别的角色。
restore
即进行数据还原的权限,实例级别的角色,还包含很多与dbOwner重合的权限,参见官网中的相关解释。
All-Database Roles:
readAnyDatabase
提供针对除了local和config库外所有其他库的读权限。
readWriteAnyDatabase
提供针对除了local和config库外所有其他库的读写权限。
userAdminAnyDatabase
同userAdmin角色,只不过范围扩大到了所有库。
dbAdminAnyDatabase
同dbAdmin角色,只不过范围扩大到了所有库。
Superuser Roles:
root
即超级用户的权限,拥有此权限你可以管理任意数据库,可以将此角色理解为dbOwner of All Database。
Internal Role:
__system
系统内置角色,拥有很高的权限(高于root),在做一些集群操作时可以使用此包含此角色的用户
一般不推荐设置此角色的用户,使用keyfile进行internal auth的副本集之间的交互就是使用此角色的。
一般来说应用使用的用户只需要readWrite角色即可,DBA可使用root账户和__system账户进行诸如集群配置,备份恢复等操作。
如何查看用户的权限:
use admin
db.system.users.find() //所有库的用户全部存在admin的system.users中
或者
use db_name
show users
三、如何开启验证登陆:
之前说了如何创建用户和指定权限,那么如何使用户登录验证生效呢?
在配置文件添加auth=true参数重启之后即可生效(如果是集群环境只配置keyfile也可以),然后登陆:
use db_name //用户必须切换到其相应的库登陆。3.6版本中默认登陆的一般是test库,所以要注意使用use dbname切换到用户对应的库
db.auth('xxx','xxx') //登陆相应的库之后就可以操作数据啦
--或者直接在命令行中登陆:
mongo db_name -u username -p password
四、关于Localhost Exception
https://docs.mongodb.com/manual/core/security-users/#localhost-exception
mongodb配置文件中有个配置项enableLocalhostAuthBypass,其默认值为1(true)。
这个参数=1的含义是:
如果你设置了auth=true,但是还未创建user或者不知道原来的用户密码想新建一个,那么此参数允许你在本地登陆时创建用户,然后使用此新建的用户验证登录。
相应的如果此参数为0,那么如果你未创建用户或者忘记了账号密码,那么即便在本地登陆mongo shell,也不允许你新建用户。
因此官网建议将此参数设置为0或false,从而防止有人可以在服务器本地新建超级权限的用户。
这个参数在初始安装时有点用,例如你开启了auth认证但是还没建超级账户的场景,不过刚安装完成时一般连auth都不会开,这个参数鸡肋。
保险起见这里还是贴下enableLocalhostAuthBypass参数的设置方法:
在配置文件里添加setParameter=enableLocalhostAuthBypass=1,然后重启(这是非YAML的设置方式,YAML的设置方式官网示例很完善了动手去查下就知道)。
https://docs.mongodb.com/v3.6/core/security-users/#sharded-cluster-users
mongodb还针对sharding集群提供了shard cluster user,普通的副本集内用户称作shard local user,集群用户可以通过mongos登陆并操作整个集群的数据,但是shard local user只能操作特定的shard副本集,例如 cleanupOrphaned, compact, rs.reconfig()等操作可以使用本地用户执行。
在mongos上创建的用户属于shard cluster user,在shard副本集本地节点创建的用户就是shard local user了。在mongo2.6之后集群用户是存储在config server上的。
一般来说没必要纠结集群用户和普通应用用户,对分片的集合使用集群用户,不分片的使用本地用户查询某个shard副本集也可以。
mongodb官网是建议对于shard集群使用集群用户连接mongos来操作集群,而本地用户只用于进行单个shard的管理和配置。这应该是出于维护数据一致性的需求,对于那些未分片的集合操作本地shard应该是可以的,但是因为我生产上也没部署过shard集群,所以实际生产中的最优实践大家根据自己的实际情况抉择。
更多的关于集群用户的相关知识参见上述官网链接,这里不再详述。
关于集群验证:
在之前介绍了如何为mongo开启用户验证,但是如果是replica或shard环境怎么办?副本集节点间也是需要交流沟通的,这样才能进行数据同步,那么直接把账密写入配置文件吗?不,mongodb选择创建一个keyfile实现集群间的权限验证以便进行信息交互。
keyfile的内容可以是字符,但是保险起见一般使用工具生成:
openssl rand -base64 756 > /etc/mongo-keyfile
chown mongod.mongod /etc/mongo-keyfile
chmod 400 /etc/mongo-keyfile
--keyfile的权限只能是400,过高会导致节点无法启动
然后将keyfile拷贝至副本集各个节点,并在配置文件中开启keyFile选项即可。
需要特别提醒的是集群环境下如果开启账户密码验证,那么只配置keyfile也是可以的,因为keyFile配置项默认会开启authorization。官网原话是:keyFile implies security.authorization. 即keyfile项意味着auth同时开启。
MongoDB用户验证和权限管理的更多相关文章
- NopCommerce源代码分析之用户验证和权限管理
目录 1. 介绍 2. UML 2.1 实体类UML图 2.2 业务相关UML图 3. 核心代码分析 3.1 实体类源代码 3.2 业务相关源代码 3.3 相关控制器源代码 3.4 ...
- mvc5+ef6+Bootstrap 项目心得--身份验证和权限管理
1.mvc5+ef6+Bootstrap 项目心得--创立之初 2.mvc5+ef6+Bootstrap 项目心得--身份验证和权限管理 3.mvc5+ef6+Bootstrap 项目心得--WebG ...
- MongoDB的账户与权限管理及在Python与Java中的登陆
本文主要介绍了MongoDB的账户新建,权限管理(简单的),以及在Python,Java和默认客户端中的登陆. 默认的MongoDB是没有账户权限管理的,也就是说,不需要密码即可登陆,即可拥有读写的权 ...
- MongoDB的账户与权限管理及在Python与Java中的登录
本文主要介绍了MongoDB的账户新建,权限管理(简单的),以及在Python,Java和默认客户端中的登陆. 默认的MongoDB是没有账户权限管理的,也就是说,不需要密码即可登陆,即可拥有读写的权 ...
- [转]mvc5+ef6+Bootstrap 项目心得--身份验证和权限管理
本文转自:http://www.cnblogs.com/shootingstar/p/5629668.html 1.mvc5+ef6+Bootstrap 项目心得--创立之初 2.mvc5+ef6+B ...
- (大数据工程师学习路径)第一步 Linux 基础入门----用户及文件权限管理
用户及文件权限管理 实验介绍 1.Linux 中创建.删除用户,及用户组等操作. 2.Linux 中的文件权限设置. 一.Linux 用户管理 Linux 是一个可以实现多用户登陆的操作系统,比如“李 ...
- Linux用户及文件权限管理
Linux用户及文件权限管理
- 实验楼学习linux第一章第三节用户及文件权限管理
用户及文件权限管理 常用命令 查看用户 whoami 创建用户 sudo adduser 用户名 切换账户 su 用户名 删除账户 sudo deluser 用户名 --remove-home 查看用 ...
- MySQL数据库(6)_用户操作与权限管理、视图、存储过程、触发器、基本函数
用户操作与权限管理 MySQL用户操作 创建用户 方法一: CREATE USER语句创建 CREATE USER "用户名"@"IP地址" IDENTIFIE ...
随机推荐
- [TimLinux] Linux shell获取进程pid
调用脚本时,获取进程PID: (/this/is/a/script/file.sh > /out/to/log.txt & echo $!) & 脚本内部,获取进程PID: ec ...
- Spring之跨重定向请求传递数据
摘要 在开发场景中,大部分数据都是使用请求转发(forward)进行传递,而使用重定向(redirect)传递数据可能比较少. 那么问题来了:请求中的数据生命周期存活时间只在一个请求转发(reques ...
- I_want_all 2019训练记录
Team members StarHai binarycopycode Fly_White Caution 读题 数组第一维的访问速度比其他维速度快. 清空数组 乘法运算取模里面涉及到减法注意变为负数 ...
- POJ 3660 cow contest (Folyed 求传递闭包)
N (1 ≤ N ≤ 100) cows, conveniently numbered 1..N, are participating in a programming contest. As we ...
- ARTS-S centos查看端口被哪个进程占用
netstat -tunlp | grep 80 或者 lsof -i:80
- Django异步任务线程池
当数据库数据量很大时(百万级),许多批量数据修改请求的响应会非常慢,一些不需要即时响应的任务可以放到后台的异步线程中完成,发起异步任务的请求就可以立即响应 选择用线程池的原因是:线程比进程更为可控.不 ...
- 【JS】379- 教你玩转数组 reduce
reduce 是数组迭代器(https://jrsinclair.com/articles/2017/javascript-without-loops/)里的瑞士军刀.它强大到您可以使用它去构建大多数 ...
- 【算法】272-每周一练 之 数据结构与算法(Dictionary 和 HashTable)
这是第五周的练习题,上周忘记发啦,这周是复习 Dictionary 和 HashTable. 下面是之前分享的链接: [算法]200-每周一练 之 数据结构与算法(Stack) [算法]213-每周一 ...
- TypeScript躬行记(3)——类
类是对对象的抽象,描述了对象的特征和行为,而对象就是类的实例.ES6引入了类的概念(相关内容可参考ES类和ES6类的继承两节),TypeScript在此基础上,不仅根据ES7等规范完善了类的语法,还添 ...
- SpringMVC深入浅出(一)
1.Springmvc是什么 是一个表现层框架,用于接受请求及参数,响应请求回显数据. 2.SpringMVC处理流程 SpringMVC流程 1. 用户发送请求至前端控制器DispatcherSe ...