MongoDb单例安全认证

MongoDb单例安全认证

1 MongoDB的用户和角色权限简介

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

mongodb官网上说,为了能保障mongodb的安全可以做以下几个步骤:
1)使用新的端口,默认的27017端口如果一旦知道了ip就能连接上,不太安全。
2)设置mongodb的网络环境,最好将mongodb部署到公司服务器内网,这样外网是访问不到的。公司内部访问使用vpn等。
3)开启安全认证。认证要同时设置服务器之间的内部认证方式,同时要设置客户端连接到集群的账号密码认证方式。为了强制开启用户访问控制(用户验证),则需要在MongoDB实例启动时使用选项 --auth 或在指定启动配置文件中添加选项 auth=true 。

在开始之前需要了解一下概念
1)启用访问控制:
MongoDB使用的是基于角色的访问控制(Role-Based Access Control,RBAC)来管理用户对实例的访问。通过对用户授予一个或多个角色来控制用户访问数据库资源的权限和数据库操作的权限,在对用户分配角色之前,用户无法访问实例。

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

3)权限:
权限由指定的数据库资源(resource)以及允许在指定资源上进行的操作(action)组成。
资源(resource)包括:数据库、集合、部分集合和集群;
操作(action)包括:对资源进行的增、删、改、查(CRUD)操作。

在角色定义时可以包含一个或多个已存在的角色,新创建的角色会继承包含的角色所有的权限。在同一个数据库中,新创建角色可以继承其他角色的权限,在 admin 数据库中创建的角色可以继承在其它任意数据库中角色的权限。
关于角色权限的查看,可以通过如下命令查询(了解):

示例:

查看所有内置角色:

> db.runCommand({ rolesInfo: 1, showBuiltinRoles: true })
{
        "roles" : [
                {
                        "role" : "__queryableBackup",
                        "db" : "admin",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "__system",
                        "db" : "admin",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "backup",
                        "db" : "admin",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "clusterAdmin",
                        "db" : "admin",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "clusterManager",
                        "db" : "admin",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "clusterMonitor",
                        "db" : "admin",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "dbAdmin",
                        "db" : "admin",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "dbAdminAnyDatabase",
                        "db" : "admin",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "dbOwner",
                        "db" : "admin",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "enableSharding",
                        "db" : "admin",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "hostManager",
                        "db" : "admin",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "read",
                        "db" : "admin",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "readAnyDatabase",
                        "db" : "admin",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "readWrite",
                        "db" : "admin",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "readWriteAnyDatabase",
                        "db" : "admin",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "restore",
                        "db" : "admin",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "root",
                        "db" : "admin",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "userAdmin",
                        "db" : "admin",
                        "isBuiltin" : true,
                        "roles" : [ ],
                        "inheritedRoles" : [ ]
                },
                {
                        "role" : "userAdminAnyDatabase",
                        "db" : "admin",
                        "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 超级账号,超级权限

单实例环境
目标:对单实例的MongoDB服务开启安全认证,这里的单实例指的是未开启副本集或分片的MongoDB实例。

2 关闭已开启的服务(可选)

增加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
//#切换到admin库
use admin
//关闭服务
db.shutdownServer()

3 添加用户和权限

(1)先按照普通无授权认证的配置,来配置服务端的配置文件 /mongodb/single/mongod.conf :

systemLog:
  #MongoDB发送所有日志输出的目标指定为文件
  destination: file
  #mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径
  path: "/mongodb/single/log/mongod.log"
  #当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾。
  logAppend: true
storage:
  #mongod实例存储其数据的目录。storage.dbPath设置仅适用于mongod。
  dbPath: "/mongodb/single/data/db"
  journal:
    #启用或禁用持久性日志以确保数据文件保持有效和可恢复。
    enabled: true
processManagement:
  #启用在后台运行mongos或mongod进程的守护进程模式。
  fork: true
  #指定用于保存mongos或mongod进程的进程ID的文件位置,其中mongos或mongod将写入其PID
  pidFilePath: "/mongodb/single/log/mongod.pid"
net:
  #绑定的端口
  port: 27017

(2)按之前未开启认证的方式(不添加 --auth 参数)来启动MongoDB服务

/usr/local/mongodb/bin/mongod -f /mongodb/single/mongod.conf

提示:
在操作用户时,启动mongod服务时尽量不要开启授权。
(3)使用Mongo客户端登录:

/usr/local/mongodb/bin/mongo  --port 2701

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

> use admin
switched to db admin
> db.createUser({user:"myroot",pwd:"123456",roles:["root"]})
Successfully added user: { "user" : "myroot", "roles" : [ "root" ] }
> db.createUser({user:"myadmin",pwd:"123456",roles:[{role:"userAdminAnyDatabase",db:"admin"}]})
Successfully added user: {
        "user" : "myadmin",
        "roles" : [
                {
                        "role" : "userAdminAnyDatabase",
                        "db" : "admin"
                }
        ]
}
> db.system.users.find()
{ "_id" : "admin.myroot", "userId" : UUID("7508ac1c-37b1-4081-ac5d-4f64e8d9decc"), "user" : "myroot", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "dhxWByEVPj2Pbmz418z2hA==", "storedKey" : "/LaVAPyLYvxAOk3BzzmdNernxz0=", "serverKey" : "7hz9apLP4je4vCFnEZQoSHe8xwU=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "AdkKzpGuUaQvJ2fUyi3KFmEQeLDrj0TkI1Ajng==", "storedKey" : "Kck8uVU/98CfXiJsq0w8lWu5/cNN8BpCepNgkIKlOOg=", "serverKey" : "LQ/KFEd7kzcrLLZtaOIr9+z82AsIy9MpmJNonnl83dE=" } }, "roles" : [ { "role" : "root", "db" : "admin" } ] }
{ "_id" : "admin.myadmin", "userId" : UUID("16bbec8b-3a67-4573-8887-713d8702f091"), "user" : "myadmin", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "IOShNy3IINnTSHaqTYzQCQ==", "storedKey" : "czcOZ7jI2kZWuTt2cNvQh2/annA=", "serverKey" : "SkPrbf96rpsamvTypSW9oJe8sLQ=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "NOLoAw/xmXzIIhbIIM1FERYU7leNu01X4EOJUg==", "storedKey" : "b+a2OsZlOWZUKnvUPqQ/M+ptdRGSb5CnuCMGwQGdxW0=", "serverKey" : "UyuWPOEvJFjYv9lh1dHOMVCxxYWJfHiX3Q8sZW13RxA=" } }, "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ] }
> db.dropUser("myadmin")
true
> db.system.users.find()
{ "_id" : "admin.myroot", "userId" : UUID("7508ac1c-37b1-4081-ac5d-4f64e8d9decc"), "user" : "myroot", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "dhxWByEVPj2Pbmz418z2hA==", "storedKey" : "/LaVAPyLYvxAOk3BzzmdNernxz0=", "serverKey" : "7hz9apLP4je4vCFnEZQoSHe8xwU=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "AdkKzpGuUaQvJ2fUyi3KFmEQeLDrj0TkI1Ajng==", "storedKey" : "Kck8uVU/98CfXiJsq0w8lWu5/cNN8BpCepNgkIKlOOg=", "serverKey" : "LQ/KFEd7kzcrLLZtaOIr9+z82AsIy9MpmJNonnl83dE=" } }, "roles" : [ { "role" : "root", "db" : "admin" } ] }
> db.changeUserPassword("myroot", "123456")
>

提示:
1)本案例创建了两个用户,分别对应超管和专门用来管理用户的角色,事实上,你只需要一个用户即可。如果你对安全要求很高,防止超管泄漏,则不要创建管用户。
2)和其它数据库(MySQL)一样,权限的管理都差不多一样,也是将用户和权限信息保存到数据库对应的表中。Mongodb存储所有的用户信息在admin 数据库的集合system.users中,保存用户名、密码和数据库信息。
3)如果不指定数据库,则创建的指定的权限的用户在所有的数据库上有效,如 {role:"userAdminAnyDatabase", db:""}

(5)认证测试
测试添加的用户是否正确

> use admin
switched to db admin
> db.auth("myroot","12345")
Error: Authentication failed.
0
> db.auth("myroot","123456")
1
>

(6)创建普通用户

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

> use articledb
switched to db articledb
> db.createUser({user: "dalianpai", pwd: "123456", roles: [{ role: "readWrite", db:"articledb" }]})
Successfully added user: {
        "user" : "dalianpai",
        "roles" : [
                {
                        "role" : "readWrite",
                        "db" : "articledb"
                }
        ]
}
>

提示:
如果开启了认证后,登录的客户端的用户必须使用admin库的角色,如拥有root角色的myadmin用户,再通过myadmin用户去创建其他角色的用户

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

(1)以开启认证的方式启动服务
有两种方式开启权限认证启动服务:一种是参数方式,一种是配置文件方式。
1)参数方式
在启动时指定参数 --auth ,如:

/usr/local/mongodb/bin/mongod -f /mongodb/single/mongod.conf --auth

2)配置文件方式
在mongod.conf配置文件中加入:
vim /mongodb/single/mongod.conf

security:
  #开启授权认证
  authorization: enabled

启动时可不加 --auth 参数:

/usr/local/mongodb/bin/mongod -f /mongodb/single/mongod.conf

(2)开启了认证的情况下的客户端登录
有两种认证方式,一种是先登录,在mongo shell中认证;一种是登录时直接认证。
1)先连接再认证

db.auth("myroot","123456")

2)连接时直接认证
对admin数据库进行登录认证和相关操作:

/usr/local/mongodb/bin/mongo --port 27017 --authenticationDatabase articledb -u dalianpai -p 123456

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

5 SpringDataMongoDB连接认证

使用用户名和密码连接到 MongoDB 服务器,你必须使用'username:password@hostname/dbname' 格式,'username'为用户名,'password' 为密码。
目标:使用用户bobo使用密码 123456 连接到MongoDB 服务上。application.yml:

**uri: mongodb://dalianpai:123456@192.168.1.104:27017/articledb **

posted @ 2020-10-11 23:56  天宇轩-王  阅读(172)  评论(0编辑  收藏  举报