官方参考页面:

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用户验证和权限管理的更多相关文章

  1. NopCommerce源代码分析之用户验证和权限管理

    目录 1.  介绍 2.  UML 2.1  实体类UML图 2.2  业务相关UML图 3.  核心代码分析 3.1  实体类源代码 3.2  业务相关源代码 3.3  相关控制器源代码 3.4  ...

  2. mvc5+ef6+Bootstrap 项目心得--身份验证和权限管理

    1.mvc5+ef6+Bootstrap 项目心得--创立之初 2.mvc5+ef6+Bootstrap 项目心得--身份验证和权限管理 3.mvc5+ef6+Bootstrap 项目心得--WebG ...

  3. MongoDB的账户与权限管理及在Python与Java中的登陆

    本文主要介绍了MongoDB的账户新建,权限管理(简单的),以及在Python,Java和默认客户端中的登陆. 默认的MongoDB是没有账户权限管理的,也就是说,不需要密码即可登陆,即可拥有读写的权 ...

  4. MongoDB的账户与权限管理及在Python与Java中的登录

    本文主要介绍了MongoDB的账户新建,权限管理(简单的),以及在Python,Java和默认客户端中的登陆. 默认的MongoDB是没有账户权限管理的,也就是说,不需要密码即可登陆,即可拥有读写的权 ...

  5. [转]mvc5+ef6+Bootstrap 项目心得--身份验证和权限管理

    本文转自:http://www.cnblogs.com/shootingstar/p/5629668.html 1.mvc5+ef6+Bootstrap 项目心得--创立之初 2.mvc5+ef6+B ...

  6. (大数据工程师学习路径)第一步 Linux 基础入门----用户及文件权限管理

    用户及文件权限管理 实验介绍 1.Linux 中创建.删除用户,及用户组等操作. 2.Linux 中的文件权限设置. 一.Linux 用户管理 Linux 是一个可以实现多用户登陆的操作系统,比如“李 ...

  7. Linux用户及文件权限管理

    Linux用户及文件权限管理

  8. 实验楼学习linux第一章第三节用户及文件权限管理

    用户及文件权限管理 常用命令 查看用户 whoami 创建用户 sudo adduser 用户名 切换账户 su 用户名 删除账户 sudo deluser 用户名 --remove-home 查看用 ...

  9. MySQL数据库(6)_用户操作与权限管理、视图、存储过程、触发器、基本函数

    用户操作与权限管理 MySQL用户操作 创建用户 方法一: CREATE USER语句创建 CREATE USER "用户名"@"IP地址" IDENTIFIE ...

随机推荐

  1. [TimLinux] Linux shell获取进程pid

    调用脚本时,获取进程PID: (/this/is/a/script/file.sh > /out/to/log.txt & echo $!) & 脚本内部,获取进程PID: ec ...

  2. Spring之跨重定向请求传递数据

    摘要 在开发场景中,大部分数据都是使用请求转发(forward)进行传递,而使用重定向(redirect)传递数据可能比较少. 那么问题来了:请求中的数据生命周期存活时间只在一个请求转发(reques ...

  3. I_want_all 2019训练记录

    Team members StarHai binarycopycode Fly_White Caution 读题 数组第一维的访问速度比其他维速度快. 清空数组 乘法运算取模里面涉及到减法注意变为负数 ...

  4. POJ 3660 cow contest (Folyed 求传递闭包)

    N (1 ≤ N ≤ 100) cows, conveniently numbered 1..N, are participating in a programming contest. As we ...

  5. ARTS-S centos查看端口被哪个进程占用

    netstat -tunlp | grep 80 或者 lsof -i:80

  6. Django异步任务线程池

    当数据库数据量很大时(百万级),许多批量数据修改请求的响应会非常慢,一些不需要即时响应的任务可以放到后台的异步线程中完成,发起异步任务的请求就可以立即响应 选择用线程池的原因是:线程比进程更为可控.不 ...

  7. 【JS】379- 教你玩转数组 reduce

    reduce 是数组迭代器(https://jrsinclair.com/articles/2017/javascript-without-loops/)里的瑞士军刀.它强大到您可以使用它去构建大多数 ...

  8. 【算法】272-每周一练 之 数据结构与算法(Dictionary 和 HashTable)

    这是第五周的练习题,上周忘记发啦,这周是复习 Dictionary 和 HashTable. 下面是之前分享的链接: [算法]200-每周一练 之 数据结构与算法(Stack) [算法]213-每周一 ...

  9. TypeScript躬行记(3)——类

    类是对对象的抽象,描述了对象的特征和行为,而对象就是类的实例.ES6引入了类的概念(相关内容可参考ES类和ES6类的继承两节),TypeScript在此基础上,不仅根据ES7等规范完善了类的语法,还添 ...

  10. SpringMVC深入浅出(一)

    1.Springmvc是什么 是一个表现层框架,用于接受请求及参数,响应请求回显数据. 2.SpringMVC处理流程 SpringMVC流程 1.  用户发送请求至前端控制器DispatcherSe ...