安全认证概述
MongoDB 默认是没有账号的,可以直接连接,无须身份验证。实际项目中肯定是要权限验证的,否则后果不堪设想。从2016年开始 发生了多起MongoDB黑客赎金事件,大部分MongoDB安全问题 暴露出了安全问题的短板其实是用户,首先用户对于数据库的安全不重视,其次用户在使用过程中可能没有养成定期备份的好习惯,最后是企业可能缺乏有经验和技术的专业人员。所以对MongoDB进行安全认证是必须要做的。
用户相关操作
切换到admin数据库对用户的添加
use admin;
db.createUser(userDocument):用于创建 MongoDB 登录用户以及分配权限的方法
db.createUser(
{
user: "账号",
pwd: "密码",
roles: [
{ role: "角色", db: "安全认证的数据库" },
]
}
)
user:创建的用户名称,如 admin、root 、lagou
pwd:用户登录的密码
roles:为用户分配的角色,不同的角色拥有不同的权限,参数是数组,可以同时设置多个
role:角色,MonngoDB 已经约定好的角色,不同的角色对应不同的权限 后面会对role做详细解释
db:数据库实例名称,如 MongoDB 4.0.2 默认自带的有 admin、local、config、test 等,即为哪个数据库实例 设置用户
举例:
db.createUser(
{
user:"root",
pwd:"123321",
roles:[{role:"root",db:"admin"}]
}
)
修改密码
db.changeUserPassword( ‘root’ , ‘rootNew’ );
用户添加角色
db.grantRolesToUser( ‘用户名’ , [{ role: ‘角色名’ , db: ‘数据库名’}])
以auth 方向启动mongod
./bin/mongod -f conf/mongo.conf --auth
(也可以在mongo.conf 中添加auth=true 参数)
验证用户
db.auth(“账号”,“密码”)
删除用户
db.dropUser(“用户名”)
角色
数据库内置的角色
查询数据库的内置角色
> db.runCommand({ rolesInfo: 1, showBuiltinRoles: true })
{
"roles" : [
{
"role" : "dbAdmin",
"db" : "test",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
},
{
"role" : "dbOwner",
"db" : "test",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
},
{
"role" : "enableSharding",
"db" : "test",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
},
{
"role" : "read",
"db" : "test",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
},
{
"role" : "readWrite",
"db" : "test",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
},
{
"role" : "userAdmin",
"db" : "test",
"isBuiltin" : true,
"roles" : [ ],
"inheritedRoles" : [ ]
}
],
"ok" : 1
}
>
常用的内置角色:
-
数据库用户角色:read、readWrite;
-
所有数据库用户角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
-
数据库管理角色:dbAdmin、dbOwner、userAdmin;
-
集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;
-
备份恢复角色:backup、restore;
-
超级用户角色:root
-
内部角色:system
角色说明:
角色 | 权限描述 |
---|---|
read | 可以读取指定数据库中任何数据。 |
readWrite | 可以读写指定数据库中任何数据,包括创建、重命名、删除集合。 |
readAnyDatabase | 可以读取所有数据库中任何数据(除了数据库config和local之外)。 |
readWriteAnyDatabase | 可以读写所有数据库中任何数据(除了数据库config和local之外)。 |
userAdminAnyDatabase | 可以在指定数据库创建和修改用户(除了数据库config和local之外)。 |
dbAdminAnyDatabase | 可以读取任何数据库以及对数据库进行清理、修改、压缩、获取统计信息、执行检查等操作(除了数据库config和local之外)。 |
dbAdmin | 可以读取指定数据库以及对数据库进行清理、修改、压缩、获取统计信息、执行检查等操作。 |
userAdmin | 可以在指定数据库创建和修改用户。 |
clusterAdmin | 可以对整个集群或数据库系统进行管理操作。 |
backup | 备份MongoDB数据最小的权限。 |
restore | 从备份文件中还原恢复MongoDB数据(除了system.profile集合)的权限。 |
root | 超级账号,超级权限 |
单机安全认证实现流程
创建 mydb1 数据库并创建了两个用户,zhangsan 拥有读写权限,lisi 拥有只读权限测试这两个账户的权限。
以超级管理员登录测试权限。
创建管理员
MongoDB 服务端开启安全检查之前,至少需要有一个管理员账号,admin 数据库中的用户都被视为管理员
如果 admin 库没有任何用户的话,即使在其他数据库中创建了用户,启用身份验证,默认的连接方式
依然会有超级权限,即仍然可以不验证账号密码照样能进行 CRUD,安全认证相当于无效。
use admin
switched to db admin
> db
admin
> db.createUser(
{
user:"root",
pwd:"123456",
roles:[{role:"root",db:"admin"}]
})
查看当前已存在的用户
db.system.users.find().pretty()
{
"_id" : "admin.root",
"userId" : UUID("a9222f44-0121-402b-9248-e7af436ac135"),
"user" : "root",
"db" : "admin",
"credentials" : {
"SCRAM-SHA-1" : {
"iterationCount" : 10000,
"salt" : "/IMIV9ouZCT9QUZ5LyyTRA==",
"storedKey" : "cCNJHUx6KGz02v6Px6kpSMtcu2w=",
"serverKey" : "eOCNuJz/2d/vSCN2R7aSFtgPQbU="
},
"SCRAM-SHA-256" : {
"iterationCount" : 15000,
"salt" : "gXIwslRQyy6reGYG9O6j8cDjKGmVa/C5AoAHqQ==",
"storedKey" : "YJg316Z2vckJtzukw+o+FkvjZZ4wsxUG7DRDNV9i6qE=",
"serverKey" : "CnGoL8nEbECABluQX+X0rRgknFvioesbHScwRyOQAi8="
}
},
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
认证测试
> db.auth("root","124")
Error: Authentication failed.
0
> db.auth("root","123456")
1
创建普通用户
创建普通用户可以在没有开启认证的时候添加,也可以在开启认证之后添加,但开启认证之后,必须使用有操作admin库的用户登录认证后才能操作。底层都是将用户信息保存在了admin数据库的集合system.users中。
//创建(切换)将来要操作的数据库articledb,一定要切换到需要创建的用户的库才能执行下面的创建操作
> use articledb
switched to db articledb
> db.createUser({user: "bobo", pwd: "123456", roles: [{ role: "readWrite", db:"articledb" }]})
Successfully added user: {
"user" : "bobo",
"roles" : [
{
"role" : "readWrite",
"db" : "articledb"
}
]
}
> db.auth('bobo','123456')
1
接着从客户端关闭 MongoDB 服务端,之后服务端会以安全认证方式进行启动
use admin
db.shutdownServer()
服务端开启认证和客户端连接登录
需要几个条件:
有两种方式开启权限认证启动服务:一种是参数方式,一种是配置文件方式。
1)参数方式
在启动时指定参数–auth ,如:
./bin/mongod -f mongod.conf --auth
(2) 配置文件方式
在mongod.conf配置文件中加入:
vim /mongodb/single/mongod.conf
security:
#开启授权认证
authorization: enabled
启动时可不加–auth 参数 :
./bin/mongod -f mongod.conf
(3)开启了认证的情况下的客户端登录
有两种认证方式,一种是先登录,在mongo shell中认证;一种是登录时直接认证。
- 先连接再认证
提示:./bin/mongo MongoDB shell version v4.2.13 connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("f92d52b9-83be-4a36-a7ca-c1944be128d8") } MongoDB server version: 4.2.13 >
开启认证后再登录,发现打印的日志比较少了。
相关操作需要认证才可以:
查询admin库中的system.users集合的用户:
查询articledb库中的comment集合的内容:> use admin switched to db admin > db.system.users.find() Error: error: { "ok" : 0, "errmsg" : "command find requires authentication", "code" : 13, "codeName" : "Unauthorized" } > db.auth('root','123456') 1 > db.system.users.find()
use articledb switched to db articledb > db.comment.find() Error: error: { "ok" : 0, "errmsg" : "command find requires authentication", "code" : 13, "codeName" : "Unauthorized" } > db.auth('bobo','123456')
- 连接时直接认证
对admin数据库进行登录认证和相关操作:/bin/mongo --authenticationDatabase admin -u root -p 123456 /bin/mongo --authenticationDatabase articledb-u bobo-p 123456
分片集群安全认证
第一步:生成一个key文件到当前文件夹中。
可以使用任何方法生成密钥文件。例如,以下操作使用openssl生成密码文件,然后使用chmod来更改文件权限,仅为文件所有者提供读取权限
openssl rand -base64 90 -out ./mongo.keyfile
chmod 400 ./mongo.keyfile
提示:
所有副本集节点都必须要用同一份keyfile,一般是在一台机器上生成,然后拷贝到其他机器上,并且权限为600 或者 400,否则将来会报错: permissions on /mongodb/replica_sets/myrs_27017/mongo.keyfile are too open
一定要保证密钥文件一致,文件位置随便。但是为了方便查找,建议每台机器都放到一个固定的位置,都放到和配置文件一起的目录中。
配置节点集群和分片节点集群开启安全认证和指定密钥文件
修改配置文件指定keyfile
分别编辑几个服务的mongod.conf文件,添加相关内容:
security:
#KeyFile鉴权文件
keyFile: /root/mongodb/mongodb/mongo.keyfile
##开启认证方式运行
authorization: enabled
在路由配置文件中 设置密钥文件
security:
#KeyFile鉴权文件
keyFile: /root/mongodb/mongodb/mongo.keyfile
说明:单独在路由上加了权限认证后 ,默认无法单独进入具体的分片查看数据 ,如果想单独进入分片查看数据则需要和路由权限认证方式相同的操作,去给配置主节点以及每个分片主节点都加相同用户名和密码的权限认证
Spring boot 连接安全认证的分片集群
先创建articledb,同时添加用户
use articledb
db.comment.insertOne({'articleid':'100001','content':'早饭还得吃热的','userid':'1005','nickname':'伊人憔悴','createdatetime':new ISODate('2020-08-05T23:58:51.485Z'),'likenum':NumberInt(1024),'state':'1'});
db.createUser({user:"elvis", pwd:"123456", roles:[{role:"readWrite", db:"articledb"}]})
然后修改之前使用的springboot工程做修改,这里碰到个奇怪的地方,我使用uri访问的时候能正常,但是用下面的配置用户名密码的方式就是返回认证失败,暂时不知道原因,同时这里也不能使用创建的root用户访问,只能使用在相应的表中创建的用户登录才能认证成功。
spring:
data:
mongodb:
uri: mongodb://elvis:123456@192.168.31.10/articledb
# username: elvis
# password: 123456
# host: 192.168.31.10
# port: 27017
# database: articledb