MongoDB 安全认证

用户和角色权限简介

默认情况下,MongoDB实例启动运行时是没有启用用户访问权限控制的,也就是说,在实例本机服务器上都可以随意连接到实例进行各种操作,MongoDB不会对连接客户端进行用户验证,这是非常危险的。

为了强制开启用户访问控制(用户验证),则需要在MongoDB实例启动时使用选项 –auth 或在指定启动配置文件中添加选项 auth=true 。

角色:在MongoDB中通过角色对用户授予相应数据库资源的操作权限,每个角色当中的权限可以显式指定, 也可以通过继承其他角色的权限,或者两都都存在的权限。

权限:权限由指定的数据库资源(resource)以及允许在指定资源上进行的操作(action)组成。

  1. 资源(resource)包括:数据库、集合、部分集合和集群;
  2. 操作(action)包括:对资源进行的增、删、改、查(CRUD)操作。

关于角色权限的查看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 关于角色权限的查看
db.runCommand({ rolesInfo: 1 })

// 查询所有角色权限(包含内置角色)
db.runCommand({ rolesInfo: 1, showBuiltinRoles: true })

// 查询当前数据库中的某角色的权限
db.runCommand({ rolesInfo: "<rolename>" })

// 查询其它数据库中指定的角色权限
db.runCommand({ rolesInfo: { role: "<rolename>", db: "<database>" } }

// 查询多个角色权限
db.runCommand(
{
rolesInfo: [
"<rolename>",
{ role: "<rolename>", db: "<database>" },
...
]
}
)

常用的内置角色:

  • 数据库用户角色:read、readWrite
  • 所有数据库用户角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
  • 数据库管理角色:dbAdmin、dbOwner、userAdmin
  • 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager
  • 备份恢复角色:backup、restore
  • 超级用户角色:root
  • 内部角色:system

角色说明:

创建用户和角色

创建两个管理员用户,一个是系统的超级管理员 myroot ,一个是admin库的管理用户 myadmin :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//切换到admin库
use admin

// 创建系统超级用户 myroot,设置密码123456,设置角色root
db.createUser({user:"myroot",pwd:"123456",roles:["root"]})

// 创建专门用来管理admin库的账号myadmin,只用来作为用户权限的管理
db.createUser({user:"myadmin",pwd:"123456",roles:[{role:"userAdminAnyDatabase",db:"admin"}]})

//查看已经创建了的用户的情况
db.system.users.find()

// 删除用户
db.dropUser("myadmin")

// 修改密码
db.changeUserPassword("myroot", "123456")

// 认证测试
db.auth("myroot","123456")

注意:如果不指定数据库,则创建的指定的权限的用户在所有的数据库上有效,如: {role: "userAdminAnyDatabase", db:""}

创建普通用户:

1
2
3
4
5
//创建(切换)将来要操作的数据库articledb
use articledb

// 创建用户,拥有articledb数据库的读写权限readWrite,密码是123456
db.createUser({user: "bobo", pwd: "123456", roles: [{ role: "readWrite", db:"articledb" }]})

注意:创建普通用户可以在没有开启认证的时候添加,也可以在开启认证之后添加,但开启认证之后,必须使 用有操作admin库的用户登录认证后才能操作。底层都是将用户信息保存在了admin数据库的集合 system.users中。

服务端开启认证和客户端连接登录

  1. 关闭已经启动的服务
  • 使用linux命令杀死进程:ps -ef |grep mongo 查看进程,然后通过kill -2 23482命令杀死进程
  • 在mongo客户端中使用shutdownServer命令来关闭:db.shutdownServer(),需要再admin库执行
  1. 开启认证的方式启动服务
  • 参数方式:在启动时指定参数 –auth
  • 配置文件方式:
1
2
3
security:
#开启授权认证
authorization: enabled
  1. 开启了认证的情况下的客户端登录
  • 先连接再认证:连接之后通过切换到admin库use admin ,然后执行db.auth("myroot","123456")认证
  • 连接时直接认证:/usr/local/mongodb/bin/mongo --host 180.76.159.126 --port 27017 --authenticationDatabase admin -u myroot -p 123456

提示:

  1. -u :用户名
  2. -p :密码
  3. –authenticationDatabase :指定连接到哪个库。当登录是指定用户名密码时,必须指定对应的数据库!

SpringDataMongoDB连接认证

使用用户名和密码连接到 MongoDB 服务器,必须使用username:password@hostname/dbname 格式,’username’为用户名,’password’ 为密码。

application.yml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
spring:
#数据源配置
data:
mongodb:
# 主机地址
# host: 180.76.159.126
# 数据库
# database: articledb
# 默认端口是27017
# port: 27017
#帐号
# username: bobo
#密码
# password: 123456
#单机有认证的情况下,也使用字符串连接
uri: mongodb://bobo:123456@180.76.159.126:27017/articledb

副本集环境或分片集群环境

说明

对于搭建好的mongodb副本集,为了安全,启动安全认证,使用账号密码登录。

分片集群环境说明:

  • 分片集群环境下的安全认证和副本集环境下基本上一样。
  • mongos比mongod少了authorization:enabled的配置,对于所有的mongod,才是真正的保存数据的分片。mongos只做路由,不保存数据。所以所有的 mongod开启访问数据的授权authorization:enabled。这样用户只有账号密码正确才能访问到数据。
  • 通过mongos添加的账号信息,只会保存到配置节点的服务中,具体的数据节点不保存账号信息,因此,分片中的账号信息不涉及到同步问题。

副本集环境架构如下:

image

对副本集执行访问控制需要配置两个方面:

  • 副本集和共享集群的各个节点成员之间使用内部身份验证,可以使用密钥文件或x.509证书。密钥文件比较简单,本文使用密钥文件,官方推荐如果是测试环境可以使用密钥文件,但是正式环境,官方推荐x.509证书。原理就是,集群中每一个实例彼此连接的时候都检验彼此使用的证书的内容是否相同。 只有证书相同的实例彼此才可以访问。
  • 使用客户端连接到mongodb集群时,开启访问授权。对于集群外部的访问。如通过可视化客户端, 或者通过代码连接的时候,需要开启授权。

说明:在keyfile身份验证中,副本集中的每个mongod实例都使用keyfile的内容作为共享密码,只有具有正确 密钥文件的mongod或者mongos实例可以连接到副本集。密钥文件的内容必须在6到1024个字符之 间,并且在unix/linux系统中文件所有者必须有对文件至少有读的权限。

通过主节点添加一个管理员帐号

只需要在主节点上添加用户,副本集会自动同步。

1
2
3
4
5
// admin库
use admin

// 创建管理员
db.createUser({user:"myroot",pwd:"123456",roles:["root"]})

提示:

该步骤也可以在开启认证之后,但需要通过localhost登录才允许添加用户,用户数据也会自动同步到副本集。

后续再创建其他用户,都可以使用该超管用户创建。

创建副本集认证的key文件

可以使用任何方法生成密钥文件。例如,以下操作使用openssl生成密码文件,然后使用chmod来更改文件权限,仅为文件所有者提供读取权限。

1
2
3
4
5
// 生成密钥文件
openssl rand -base64 90 -out ./mongo.keyfile

// 修改文件权限
chmod 400 ./mongo.keyfile

说明:一定要保证所有服务密钥文件一致,文件位置随便。

修改配置文件

修改副本集配置文件,指定密钥文件位置。

1
2
3
4
5
security:
#KeyFile鉴权文件
keyFile: /mongodb/replica_sets/myrs_27017/mongo.keyfile
#开启认证方式运行
authorization: enabled

SpringDataMongoDB连接副本集

application.yml:

1
2
3
4
5
6
7
8
9
spring:
#数据源配置
data:
mongodb:
#副本集有认证的情况下,字符串连接
uri:
mongodb://bobo:123456@180.76.159.126:27017,180.76.159.126:27018,180.76.159.126:2
7019/articledb?connect=replicaSet&slaveOk=true&replicaSet=myrs