官方参考页面:

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. MRC ARC 混编

    今天一个人问我 什么是MRC 什么是ARC 要是一个工程里用到了MRC和ARC 怎么办 我当时就无语了 什么情况 这是....   好了正经一点 我说一下iOS5.0以后就开始可以使用ARC( Aut ...

  2. EasyUI整合SpringBoot,Spring Data对数据的分页操作

    EasyUI的用法可以看中文官网,看插件是如何使用的 EasyUI中文官网 前端页面 <table id="dg" title="My Users" cl ...

  3. Zabbix与ELK整合实现对日志数据的实时监控

    4.2.zabbix平台配置日志告警 一. ELK与zabbix有什么关系? ELK大家应该比较熟悉了,zabbix应该也不陌生,那么将ELK和zabbix放到一起的话,可能大家就有疑问了?这两个放到 ...

  4. 基于USB3.0的双目相机测试小结之CC1605配合CS5642 双目 500w摄像头

    基于USB3.0的双目相机测试小结之CC1605配合CS5642  双目 500w摄像头 CC1605双目相机评估板可以配合使用柴草电子绝大多数摄像头应用 如:OV5640.OV5642.MT9P03 ...

  5. DRF Django REST framework 之 路由器与版本控制组件(七)

    路由器 一些Web框架提供了用于自动确定应如何将应用程序的URL映射到处理传入请求的逻辑的功能. 而DRF的路由器组件也提供了一种简单,快速且一致的方式将视图逻辑映射到一组URL上. 路由器组件的使用 ...

  6. 使用 defineProperty 劫持数据属性的改变

    使用defineProperty劫持数据属性的变化 例子一:有一个全局变量a,有一个全局函数b,实现一个`bindData`,执行后,a的任何赋值都会触发b的执行 // var a = 1;a = 1 ...

  7. java概述和java环境按照,java开发体验

    java概述: Java的发展可以归纳如下的几个阶段. (1)第一阶段(完善期):JDK 1.0 ( 1995年推出)一JDK 1.2 (1998年推出,Java更名为Java 2): (2)第二阶段 ...

  8. Docker--Docker初体验

    echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!!! 先来接 ...

  9. elasticsearch搜索QueryStringQueryBuilder时的一些问题记录

    首先看下原始数据 但是 如果使用英文查询的时候又和上面有点区别了,感觉还是分词器的问题

  10. 【集合系列】- 深入浅出分析 ArrayDeque

    一.摘要 在 jdk1.5 中,新增了 Queue 接口,代表一种队列集合的实现,咱们继续来聊聊 java 集合体系中的 Queue 接口. Queue 接口是由大名鼎鼎的 Doug Lea 创建,中 ...