1、MongoDB的用户和角色权限简介
默认情况下,MongoDB实例启动运行时是没有启用用户访问权限控制的,也就是说,在实例本机服务器上都可以随意连接到实例进行各种作,MongoDB不会对连接客户端进行用户验证,这是非常危险的。
mongodb官网上说,为了能保障mongodb的安全可以做以下几个步骤:
- 使用新的端口,默认的27017端口如果一旦知道了ip就能连接上,不太安全。
- 设置mongodb的网络环境,最好将mongodb部署到公司服务器内网,这样外网是访问不到的。公司内部访问使用vpn等。
- 开启安全认证。认证要同时设置服务器之间的内部认证方式,同时要设置客户端连接到集群的账号密码认证方式。
为了强制开启用户访问控制(用户验证),则需要在MongoDB实例启动时使用选项 --auth 或在指定启动配置文件中添加选项 auth=true 。
1.1、启用访问控制:
MongoDB使用的是基于角色的访问控制(Role-Based Access Control,RBAC)来管理用户对实例的访问。
通过对用户授予一个或多个角色来控制用户访问数据库资源的权限和数据库操作的权限,在对用户分配角色之前,用户无法访问实例。
在实例启动时添加选项 --auth 或指定启动配置文件中添加选项 auth=true 。
1.2、角色:
在MongoDB中通过角色对用户授予相应数据库资源的操作权限,每个角色当中的权限可以显式指定,也可以通过继承其他角色的权限,或者两都都存在的权限。
1.3、权限:
权限由指定的数据库资源(resource)以及允许在指定资源上进行的操作(action)组成。
- 资源(resource)包括:数据库、集合、部分集合和集群;
- 操作(action)包括:对资源进行的增、删、改、查(CRUD)操作。
在角色定义时可以包含一个或多个已存在的角色,新创建的角色会继承包含的角色所有的权限。在同一个数据库中,新创建角色可以继承其他角色的权限,在 admin 数据库中创建的角色可以继承在其它任意数据库中角色的权限。
1.4、查看关于角色权限的命令(了解):
1.4.1、查询所有角色权限(仅用户自定义角色)
db.runCommand({ rolesInfo: 1 })
1.4.2、查询所有角色权限(包含内置角色)
db.runCommand({ rolesInfo: 1, showBuiltinRoles: true })
1.4.3、查询当前数据库中的某角色的权限
db.runCommand({ rolesInfo: "<rolename>" })
1.4.4、查询其它数据库中指定的角色权限
db.runCommand({ rolesInfo: { role: "<rolename>", db: "<database>" } }
1.4.5、查询多个角色权限
db.runCommand( { rolesInfo: [ "<rolename>", { role: "<rolename>", db: "<database>" }, ... ] } )
示例:查看所有内置角色:
db.runCommand({ rolesInfo: 1, showBuiltinRoles: true })
1.5、常用的内置角色:
- 数据库用户角色:read、readWrite;
- 所有数据库用户角色:readAnyDatabase、readWriteAnyDatabase、
userAdminAnyDatabase、dbAdminAnyDatabase - 数据库管理角色:dbAdmin、dbOwner、userAdmin;
- 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;
- 备份恢复角色:backup、restore;
- 超级用户角色:root
- 内部角色:system
角色说明:
2、单实例环境
目标:对单实例的MongoDB服务开启安全认证,这里的单实例指的是未开启副本集或分片的MongoDB实例。
2.1、关闭已开启的服务(可选)
增加mongod的单实例的安全认证功能,可以在服务搭建的时候直接添加,也可以在之前搭建好的服务上添加。
本文使用之前搭建好的服务,因此,先停止之前的服务
停止服务的方式有两种:快速关闭和标准关闭,下面依次说明: (1)快速关闭方法(快速,简单,数据可能会出错)
目标:通过系统的kill命令直接杀死进程:
杀完要检查一下,避免有的没有杀掉。
kill -2 54410
【补充】 如果一旦是因为数据损坏,则需要进行如下操作(了解): 1)删除lock文件:
rm -f /mongodb/single/data/db/*.lock
2)修复数据:
/usr/local/mongodb/bin/mongod --repair --dbpath=/mongodb/single/data/db
(2)标准的关闭方法(数据不容易出错,但麻烦):
目标:通过mongo客户端中的shutdownServer命令来关闭服务
主要的操作步骤参考如下:
//客户端登录服务,注意,这里通过localhost登录,如果需要远程登录,必须先登录认证才行。
mongo --port 27017
//
use admin
//关闭服务
db.shutdownServer()
2.2、 添加用户和权限
2.2.1、配置服务端的配置文件
先按照普通无授权认证的配置,来配置服务端的配置文件 /mongodb/single/mongod.conf :(单例环境的配置可参考前面的文章)
2.2.2、按之前未开启认证的方式(不添加 --auth 参数)来启动MongoDB服务:
/usr/local/mongodb/bin/mongod -f /mongodb/single/mongod.conf
提示: 在操作用户时,启动mongod服务时尽量不要开启授权。
2.2.3、使用Mongo客户端登录:
/usr/local/mongodb/bin/mongo --host 127.0.0.1 --port 27017
2.2.4、创建两个管理员用户,一个是系统的超级管理员 myroot ,一个是admin库的管理用户myadmin :
切换到admin库
use admin
创建系统超级用户 myroot,设置密码123456,设置角色root
//db.createUser({user:"myroot",pwd:"123456",roles:[ { "role" : "root", "db" : "admin" } ]})
//或
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")
提示: 1)本案例创建了两个用户,分别对应超管和专门用来管理用户的角色,事实上,你只需要一个用户即可。如果你对安全要求很高,防止超管泄漏,则不要创建超管用户。
2)和其它数据库(MySQL)一样,权限的管理都差不多一样,也是将用户和权限信息保存到数据库对应的表中。Mongodb存储所有的用户信息在admin 数据库的集合system.users中,保存用户名、密码和数据库信息。
3)如果不指定数据库,则创建的指定的权限的用户在所有的数据库上有效,如 {role: “userAdminAnyDatabase”, db:“”}
2.2.5、认证测试
测试添加的用户是否正确
切换到admin
use admin
密码输错
db.auth("myroot","12345")
密码正确
db.auth("myroot","123456")
2.2.6、创建普通用户
创建普通用户可以在没有开启认证的时候添加,也可以在开启认证之后添加,但开启认证之后,必须使用有操作admin库的用户登录认证后才能操作。底层都是将用户信息保存在了admin数据库的集合system.users中。
创建(切换)将来要操作的数据库articledb,
use articledb
创建用户,拥有articledb数据库的读写权限readWrite,密码是123456
db.createUser({user: "bobo", pwd: "123456", roles: [{ role: "readWrite", db: "articledb" }]})
或者// db.createUser({user: "bobo", pwd: "123456", roles: ["readWrite"]})
测试是否可用
db.auth("bobo","123456")
提示:
如果开启了认证后,登录的客户端的用户必须使用admin库的角色,如拥有root角色的myadmin用户,再通过myadmin用户去创建其他角色的用户。
3、服务端开启认证和客户端连接登录
3.1、关闭已经启动的服务
3.1.1、使用linux命令杀死进程:
ps -ef |grep mongo
kill -2 23482
3.1.2、在mongo客户端中使用shutdownServer命令来关闭。
使用admin才能关闭
use admin
db.shutdownServer()
需要几个条件:
- 必须是在admin库下执行该关闭服务命令。
- 如果没有开启认证,必须是从localhost登陆的,才能执行关闭服务命令。
- 非localhost的、通过远程登录的,必须有登录且必须登录用户有对admin操作权限才可以。
3.2、以开启认证的方式启动服务
有两种方式开启权限认证启动服务:一种是参数方式,一种是配置文件方式。
3.2.1、参数方式
在启动时指定参数 --auth ,如:
/usr/local/mongodb/bin/mongod -f /mongodb/single/mongod.conf --auth
3.2.2、配置文件方式
在mongod.conf配置文件中加入:
vim /mongodb/single/mongod.conf
添加配置
security:
authorization: enabled
启动时可不加 --auth 参数:
/usr/local/mongodb/bin/mongod -f /mongodb/single/mongod.conf
3.3、开启了认证的情况下的客户端登录
有两种认证方式,一种是先登录,在mongo shell中认证;一种是登录时直接认证。
3.3.1、先连接再认证
/usr/local/mongodb/bin/mongo --host 127.0.0.1 --port 27017
提示: 开启认证后再登录,发现打印的日志比较少了。
相关操作需要认证才可以:
查询admin库中的system.users集合的用户:
use admin
db.system.users.find()
db.auth("myroot","123456")
db.system.users.find()
查询articledb库中的comment集合的内容:
use articledb
db.comment.find()
db.auth("bobo","123456")
db.comment.find()
提示: 这里可能出现错误,说是太多的用户正在认证了。因为我们确实连续登录了两个用户了。
解决方案:退出shell,重新进来登录认证。
exit
/usr/local/mongodb/bin/mongo --host 127.0.0.1 --port 27017
db.auth("bobo","123456")
use articledb
db.auth("bobo","123456")
db.comment.find()
3.3.2、连接时直接认证
对admin数据库进行登录认证和相关操作:
/usr/local/mongodb/bin/mongo --host 180.76.159.126 --port 27017 --authenticationDatabase admin -u myroot -p 123456
对articledb数据库进行登录认证和相关操作:
/usr/local/mongodb/bin/mongo --host 180.76.159.126 --port 27017 --authenticationDatabase articledb -u bobo -p 123456
提示:
- u :用户名
- p :密码
- –authenticationDatabase :指定连接到哪个库。当登录是指定用户名密码时,必须指定对应的数据库!
4、 SpringDataMongoDB连接认证
使用用户名和密码连接到 MongoDB 服务器,你必须使用’username:password@hostname/dbname’ 格式,'username’为用户名,‘password’ 为密码。
目标:使用用户bobo使用密码 123456 连接到MongoDB 服务上。
application.yml:
spring:
data:
mongodb:
uri: mongodb://bobo:123456@192.168.64.128:27017/articledb
密码正确:
密码错误:
提示: 分别测试用户名密码正确以及不正确的情况。
5、副本集环境
5.1、前言
对于搭建好的mongodb副本集,为了安全,启动安全认证,使用账号密码登录。 副本集环境使用之前搭建好的,架构如下:
对副本集执行访问控制需要配置两个方面:
-
副本集和共享集群的各个节点成员之间使用内部身份验证,可以使用密钥文件或x.509证书。密钥文件比较简单,本文使用密钥文件,官方推荐如果是测试环境可以使用密钥文件,但是正式环境,官方推荐x.509证书。原理就是,集群中每一个实例彼此连接的时候都检验彼此使用的证书的内容是否相同。只有证书相同的实例彼此才可以访问。 -
使用客户端连接到mongodb集群时,开启访问授权。对于集群外部的访问。如通过可视化客户端,或者通过代码连接的时候,需要开启授权。
在keyfile身份验证中,副本集中的每个mongod实例都使用keyfile的内容作为共享密码,只有具有正确密钥文件的mongod或者mongos实例可以连接到副本集。密钥文件的内容必须在6到1024个字符之间,并且在unix/linux系统中文件所有者必须有对文件至少有读的权限。
5.2、关闭已开启的副本集服务(可选)
增加副本集的安全认证和服务鉴权功能,可以在副本集搭建的时候直接添加,也可以在之前搭建好的副本集服务上添加。
本文使用之前搭建好的副本集服务,因此,先停止之前的集群服务
停止服务的方式有两种:快速关闭和标准关闭,下面依次说明:
5.2.1、快速关闭方法(快速,简单,数据可能会出错)
目标:通过系统的kill命令直接杀死进程:
依次杀死仲裁者、副本节点、主节点,直到所有成员都离线。建议主节点最后kill,以避免潜在的回滚。
杀完要检查一下,避免有的没有杀掉。
kill -2 54410
【补充】如果一旦是因为数据损坏,则需要进行如下操作(了解): 1)删除lock文件:
rm -f /mongodb/replica_sets/myrs_27017/data/db/*.lock \ /mongodb/replica_sets/myrs_27018/data/db/*.lock \ /mongodb/replica_sets/myrs_27019/data/db/mongod.lock \
2)依次修复数据:
/usr/local/mongodb/bin/mongod --repair -- dbpath=/mongodb/replica_sets/myrs_27017/data/db
/usr/local/mongodb/bin/mongod --repair -- dbpath=/mongodb/replica_sets/myrs_27018/data/db
/usr/local/mongodb/bin/mongod --repair -- dbpath=/mongodb/replica_sets/myrs_27019/data/db
5.2.2、标准的关闭方法(数据不容易出错,但麻烦):
目标:通过mongo客户端中的shutdownServer命令来依次关闭各个服务。
关闭副本集中的服务,建议依次关闭仲裁节点、副本节点、主节点。主要的操作步骤参考如下:
//客户端登录服务,注意,这里通过localhost登录,如果需要远程登录,必须先登录认证才行。
mongo --port 27017
//告知副本集说本机要下线
rs.stepDown()
//
use admin
//关闭服务
db.shutdownServer()
5.3、启动所有副本集
/usr/local/mongodb/bin/mongod -f /mongodb/replica_sets/myrs_27017/mongod.conf
/usr/local/mongodb/bin/mongod -f /mongodb/replica_sets/myrs_27018/mongod.conf
/usr/local/mongodb/bin/mongod -f /mongodb/replica_sets/myrs_27019/mongod.conf
5.4、通过主节点添加一个管理员帐号
/usr/local/mongodb/bin/mongo --port 27017
只需要在主节点上添加用户,副本集会自动同步。
开启认证之前,创建超管用户:myroot,密码:123456
use admin
db.createUser({user:"myroot",pwd:"123456",roles:["root"]})
详细操作详见单实例环境的 添加用户和权限 的相关操作。
提示:
该步骤也可以在开启认证之后,但需要通过localhost登录才允许添加用户,用户数据也会自动同步到副本集。
后续再创建其他用户,都可以使用该超管用户创建。
5.5、创建副本集认证的key文件
第一步:生成一个key文件到当前文件夹中。
可以使用任何方法生成密钥文件。例如,以下操作使用openssl生成密码文件,然后使用chmod来更改文件权限,仅为文件所有者提供读取权限。
openssl rand -base64 90 -out ./mongo.keyfile
chmod 400 ./mongo.keyfile
ll mongo.keyfile
提示:
所有副本集节点都必须要用同一份keyfile,一般是在一台机器上生成,然后拷贝到其他机器上,且必须有读的权限,否则将来会报错: permissions on /mongodb/replica_sets/myrs_27017/mongo.keyfile are too open
一定要保证密钥文件一致,文件位置随便。但是为了方便查找,建议每台机器都放到一个固定的位置,都放到和配置文件一起的目录中。
这里将该文件分别拷贝到多个目录中:
cp mongo.keyfile /mongodb/replica_sets/myrs_27017
cp mongo.keyfile /mongodb/replica_sets/myrs_27018
cp mongo.keyfile /mongodb/replica_sets/myrs_27019
5.6、修改配置文件指定keyfile
分别编辑几个服务的mongod.conf文件,添加相关内容: myrs_27017
vim /mongodb/replica_sets/myrs_27017/mongod.conf
mongod.conf
security:
keyFile: /mongodb/replica_sets/myrs_27017/mongo.keyfile
authorization: enabled
myrs_27018
vim /mongodb/replica_sets/myrs_27018/mongod.conf
mongod.conf
security:
keyFile: /mongodb/replica_sets/myrs_27018/mongo.keyfile
authorization: enabled
myrs_27019
vim /mongodb/replica_sets/myrs_27019/mongod.conf
mongod.conf
security:
keyFile: /mongodb/replica_sets/myrs_27019/mongo.keyfile
authorization: enabled
5.7、重新启动副本集
如果副本集是开启状态,则先分别关闭关闭复本集中的每个mongod,从次节点开始。直到副本集的所有成员都离线,包括任何仲裁者。主节点必须是最后一个成员关闭以避免潜在的回滚。
kill -2 54410 54361 54257
分别启动副本集节点:
/usr/local/mongodb/bin/mongod -f /mongodb/replica_sets/myrs_27017/mongod.conf
/usr/local/mongodb/bin/mongod -f /mongodb/replica_sets/myrs_27018/mongod.conf
/usr/local/mongodb/bin/mongod -f /mongodb/replica_sets/myrs_27019/mongod.conf
查看进程情况:
ps -ef |grep mongod
5.8、在主节点上添加普通账号
5.8.1、先用管理员账号登录
5.8.2、切换到admin库
use admin
5.8.3、管理员账号认证
db.auth("myroot","123456")
5.8.4、切换到要认证的库
use articledb
5.8.5、添加普通用户
db.createUser({user: "bobo", pwd: "123456", roles: ["readWrite"]})
重新连接,使用普通用户bobo重新登录,查看数据。
注意:也要使用rs.status()命令查看副本集是否健康。
6、SpringDataMongoDB连接副本集
使用用户名和密码连接到 MongoDB 服务器,你必须使用 ‘username:password@hostname/dbname’ 格式,'username’为用户名,‘password’ 为密码。
目标:使用用户bobo使用密码 123456 连接到MongoDB 服务上。
application.yml:
spring:
#数据源配置
data:
mongodb:
#副本集有认证的情况下,字符串连接
uri: mongodb://bobo:123456@192.168.64.128:27017,192.168.64.128:27018,192.168.64.128:27019/articledb?connect=replicaSet&slaveOk=true&replicaSet=myrs
结束!
人各有命,上天注定,脚下的路,如果不是你自己的选择,那旅途的终点在哪也没人知道。
|