赞
踩
默认情况下,MongoDB实例启动运行时是没有启用用户访问权限控制的,也就是说,在实例本机服务器上都可以随意连接到实例进行各种操作,MongoDB不会对连接客户端进行用户验证,这是非常危险的。
mongodb官网上说,为了能保障mongodb的安全可以做以下几个步骤:
1)使用新的端口,默认的27017端口如果一旦知道了ip就能连接上,不太安全。
2)设置mongodb的网络环境,最好将mongodb部署到公司服务器内网,这样外网是访问不到的。公司内部访问使用vpn等。
3)开启安全认证。认证要同时设置服务器之间的内部认证方式,同时要设置客户端连接到集群的账号密码认证方式。
为了强制开启用户访问控制(用户验证),则需要在MongoDB实例启动时使用选项 --auth 或在指定启动配置文件中添加选项 auth=true 。
在开始之前需要了解一下概念
1)启用访问控制:
MongoDB使用的是基于角色的访问控制(Role-Based Access Control,RBAC)来管理用户对实例的访问。
通过对用户授予一个或多个角色来控制用户访问数据库资源的权限和数据库操作的权限,在对用户分配角色之前,用户无法访问实例。
在实例启动时添加选项 --auth 或指定启动配置文件中添加选项 auth=true 。
2)角色:
在MongoDB中通过角色对用户授予相应数据库资源的操作权限,每个角色当中的权限可以显式指定,也可以通过继承其他角色的权限,或者两都都存在的权限。
3)权限:
权限由指定的数据库资源(resource)以及允许在指定资源上进行的操作(action)组成。
// 查询所有角色权限(仅用户自定义角色) > 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>" }, ... ] } )
示例:
查看所有内置角色:
> 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, "$gleStats" : { "lastOpTime" : Timestamp(0, 0), "electionId" : ObjectId("7fffffff0000000000000005") }, "lastCommittedOpTime" : Timestamp(1640778313, 1), "$configServerState" : { "opTime" : { "ts" : Timestamp(1640778307, 1), "t" : NumberLong(1) } }, "$clusterTime" : { "clusterTime" : Timestamp(1640778313, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(1640778313, 1) }
常用的内置角色:
角色说明:
角色 | 权限描述 |
---|---|
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
实例。
增加mongod的单实例的安全认证功能,可以在服务搭建的时候直接添加,也可以在之前搭建好的服务
上添加。
本文使用之前搭建好的服务,因此,先停止之前的服务
停止服务的方式有两种:快速关闭和标准关闭,下面依次说明:
(1)快速关闭方法(快速,简单,数据可能会出错)
目标:通过系统的kill命令直接杀死进程:
杀完要检查一下,避免有的没有杀掉。
#通过进程编号关闭节点
kill -2 进程编号
【补充】
如果一旦是因为数据损坏,则需要进行如下操作(了解):
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()
(1)先按照普通无授权认证的配置,来配置服务端的配置文件 /mongodb/single/mongod.conf
systemLog: #MongoDB发送所有日志输出的目标指定为文件 ##The path of the log file to which mongod or mongos should send all diagnostic logging information destination: file #mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径 path: "/mongodb/single/log/mongod.log" #当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾。 logAppend: true storage: #mongod实例存储其数据的目录。storage.dbPath设置仅适用于mongod。 ##The directory where the mongod instance stores its data.Default Value is "/data/db". dbPath: "/mongodb/single/data/db" journal: #启用或禁用持久性日志以确保数据文件保持有效和可恢复。 enabled: true processManagement: #启用在后台运行mongos或mongod进程的守护进程模式。 fork: true net: #服务实例绑定的IP,默认是localhost bindIp: localhost,172.22.4.227 #bindIp #绑定的端口,默认是27017 port: 27017
(2)按之前未开启认证的方式(不添加 --auth 参数)来启动MongoDB服务:
/usr/local/mongodb/bin/mongod -f /mongodb/single/mongod.conf
提示:
在操作用户时,启动mongod服务时尽量不要开启授权。
(3)使用Mongo客户端登录:
/usr/local/mongodb/bin/mongo --host 120.79.157.129 --port 27017
(4)创建两个管理员用户,一个是系统的超级管理员 myroot ,一个是admin库的管理用户
myadmin :
//切换到admin库 > use admin //创建系统超级用户 myroot,设置密码123456,设置角色root > db.createUser({user:"myroot",pwd:"123456",roles:["root"]}) Successfully added user: { "user" : "myroot", "roles" : [ "root" ] } //或 > db.createUser({user:"myroot",pwd:"123456",roles:[ { "role" : "root", "db" :"admin" } ]}) Successfully added user: { "user" : "myroot", "roles" : [ { "role" : "root", "db" : "admin" } ] }
//创建专门用来管理admin库的账号myadmin,只用来作为用户权限的管理 > 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("01c67bfb-d682-439a-b7f2-d915115094fa"), "user" : "myroot", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "h22fA1xHbWhEU/BvUQDdDA==", "storedKey" : "Ab+vBJNQGzMq8u/LUPZbuM45u3k=", "serverKey" : "bLQgiXdTDTVDwjyv66rsJR2M2/8=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "5s9XxsiFe5n2RDaNWYyv3f3NC3Q9MaR3kphNCw==", "storedKey" : "nmAMUivvCgDU/fDrVFEjMXgc/y/IRqQP30x8hPfsTi0=", "serverKey" : "jpVVmb8HjDxL7QaRUNuBbE62KJ/3TuJ86ycsEa8D6Ak=" } }, "roles" : [ { "role" : "root", "db" : "admin" } ] } { "_id" : "admin.myadmin", "userId" : UUID("fb0e140f-43e5-49ff-9df5-d2ccc6d563cc"), "user" : "myadmin", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "OnMlfgOgcZcCwhEpJcwxXg==", "storedKey" : "pRunnTBqlZ6GpomABDaUW8UKFrM=", "serverKey" : "WH7BNQpotqxFZYjgC8tuDCvPfvE=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "bS590nilQffquebLh28ig11X+ZC3LYwMJHW4vQ==", "storedKey" : "a7Da7NNIvFPHoDfYwrvGNd4Rl1YBXqK4tDRJgSSB/Ho=", "serverKey" : "c/x/TqbRwldPc0foe+wnvccyFJry5AQFRBTTtgIgJAs=" } }, "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ] } //删除用户 > db.dropUser("myadmin") true > db.system.users.find() { "_id" : "admin.myroot", "userId" : UUID("01c67bfb-d682-439a-b7f2-d915115094fa"), "user" : "myroot", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "h22fA1xHbWhEU/BvUQDdDA==", "storedKey" : "Ab+vBJNQGzMq8u/LUPZbuM45u3k=", "serverKey" : "bLQgiXdTDTVDwjyv66rsJR2M2/8=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "5s9XxsiFe5n2RDaNWYyv3f3NC3Q9MaR3kphNCw==", "storedKey" : "nmAMUivvCgDU/fDrVFEjMXgc/y/IRqQP30x8hPfsTi0=", "serverKey" : "jpVVmb8HjDxL7QaRUNuBbE62KJ/3TuJ86ycsEa8D6Ak=" } }, "roles" : [ { "role" : "root", "db" : "admin" } ] } //修改密码 > db.changeUserPassword("myroot", "123456") > 123456 123456
提示:
1)本案例创建了两个用户,分别对应超管和专门用来管理用户的角色,事实上,你只需要一个用户即可。如果你对安全要求很高,防止超管泄漏,则不要创建超管用户。
2)和其它数据库(MySQL)一样,权限的管理都差不多一样,也是将用户和权限信息保存到数据库对应的表中。Mongodb存储所有的用户信息在admin 数据库的集合system.users中,保存用户名、密码和数据库信息。
3)如果不指定数据库,则创建的指定的权限的用户在所有的数据库上有效,如 {role:“userAdminAnyDatabase”, db:""}
(5)认证测试
测试添加的用户是否正确
//切换到admin
> use admin
//密码输错
> db.auth("myroot","12345")
Error: Authentication failed.
0
//密码正确
> db.auth("myroot","123456")
1
(6)创建普通用户
创建普通用户可以在没有开启认证的时候添加,也可以在开启认证之后添加,但开启认证之后,必须使用有操作admin库的用户登录认证后才能操作。底层都是将用户信息保存在了admin数据库的集合system.users中。
//创建(切换)将来要操作的数据库articledb,
> use articledb
switched to db articledb
//创建用户,拥有articledb数据库的读写权限readWrite,密码是123456
> db.createUser({user: "common", pwd: "123456", roles: [{ role: "readWrite", db:"articledb" }]})
//> db.createUser({user: "common", pwd: "123456", roles: ["readWrite"]})
//测试是否可用
> db.auth("common","123456")
1
提示:
如果开启了认证后,登录的客户端的用户必须使用admin库的角色,如拥有root角色的myadmin用户,再通过myadmin用户去创建其他角色的用户
(1)关闭已经启动的服务
1)使用linux命令杀死进程:
[root@liar single]# ps -ef |grep mongo
root 10228 1 0 19:59 ? 00:00:37 /usr/local/mongodb/bin/mongod -f /mongodb/single/mongod.conf
[root@liar single]# kill -2 10228
2)在mongo客户端中使用shutdownServer命令来关闭。
> db.shutdownServer()
shutdown command only works with the admin database; try 'use admin'
> use admin
switched to db admin
> db.shutdownServer()
server should be down...
需要几个条件:
[root@liar single]# /usr/local/mongodb/bin/mongod -f /mongodb/single/mongod.conf --auth
about to fork child process, waiting until server is ready for connections.
forked process: 10542
child process started successfully, parent exiting
2)配置文件方式
在mongod.conf配置文件中加入:
vim /mongodb/single/mongod.conf
security:
#开启授权认证
authorization: enabled
启动时可不加 --auth 参数:
/usr/local/mongodb/bin/mongod -f /mongodb/single/mongod.conf
(3)开启了认证的情况下的客户端登录
有两种认证方式,一种是先登录,在mongo shell中认证;一种是登录时直接认证。
1)先连接再认证
[root@liar ~]# /usr/local/mongodb/bin/mongo --host=120.79.157.129 --port=27017
MongoDB shell version v4.4.11-rc1
connecting to: mongodb://120.79.157.129:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("e3fb649b-5c88-4872-8127-5fc9be1dc537") }
MongoDB server version: 4.4.11-rc1
>
开启认证后再登录,发现打印的日志比较少了。
相关操作需要认证才可以:
查询admin库中的system.users集合的用户:
> use admin
switched to db admin
> show dbs
> db.system.user.find();
Error: error: {
"ok" : 0,
"errmsg" : "command find requires authentication",
"code" : 13,
"codeName" : "Unauthorized"
}
> db.auth("myroot","123456")
1
> db.system.users.find()
{ "_id" : "admin.myroot", "userId" : UUID("01c67bfb-d682-439a-b7f2-d915115094fa"), "user" : "myroot", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "L6/49agvD0C55OA46oQG7w==", "storedKey" : "/F57ro/H23Gf/yD7TAzIcxOMsG8=", "serverKey" : "JH/fwCHqfzu0PihC0zifN6nb0po=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "FUkJXRYz8YjTBgVTh/6/nZpJfDMUbrJMErbECw==", "storedKey" : "XWzG2i5sJ0/WY3WSTABy+g8eRTx8niFQbWom9DKLeQU=", "serverKey" : "1TBmGa5hfa2Ie9wewekFweV4Ww575A07cBpl6QqCN4A=" } }, "roles" : [ { "role" : "root", "db" : "admin" } ] }
{ "_id" : "articledb.common", "userId" : UUID("c0236e43-4506-452e-957d-60ab8b7887da"), "user" : "common", "db" : "articledb", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "hENvKl6y4wBy6ZF1cV0Rvg==", "storedKey" : "tuhk/yflSo0rMK1iSXSezxmIIIY=", "serverKey" : "WvgLq5DkygtI1NKbx4kltoNbXes=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "3gWDszJVZm4W3zuYwSLgCAtnW9QUpy96K/zgAw==", "storedKey" : "gVOVQAV/lTLkStzHflMOnfYE5tiCjDHtAPQVmKGVuSE=", "serverKey" : "goIgSpcSQWbGNRcxL7PZjJct1WPOJTWuYcLamiC74j4=" } }, "roles" : [ { "role" : "readWrite", "db" : "articledb" } ] }
查询articledb库中的comment集合的内容:
> use articledb switched to db articledb > db.comment.find() Error: error: { "ok" : 0, "errmsg" : "command find requires authentication", "code" : 13, "codeName" : "Unauthorized" } > db.auth("common","123456") 1 > db.comment.find() { "_id" : "1", "articleid" : "100001", "content" : "我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。", "userid" : "1002", "nickname" : "相忘于江湖", "createdatetime" : ISODate("2019-08-05T22:08:15.522Z"), "likenum" : 1000, "state" : "1" } { "_id" : "2", "articleid" : "100001", "content" : "我夏天空腹喝凉开水,冬天喝温开水", "userid" : "1005", "nickname" : "伊人憔悴", "createdatetime" : ISODate("2019-08-05T23:58:51.485Z"), "likenum" : 888, "state" : "1" } { "_id" : "3", "articleid" : "100001", "content" : "我一直喝凉开水,冬天夏天都喝。", "userid" : "1004", "nickname" : "杰克船长", "createdatetime" : ISODate("2019-08-06T01:05:06.321Z"), "likenum" : NumberLong(667), "state" : "1" } { "_id" : "4", "articleid" : "100001", "content" : "专家说不能空腹吃饭,影响健康。", "userid" : "1003", "nickname" : "凯撒", "createdatetime" : ISODate("2019-08-06T08:18:35.288Z"), "likenum" : 2000, "state" : "1" } { "_id" : "5", "articleid" : "100001", "content" : "研究表明,刚烧开的水千万不能喝,因为烫嘴。", "userid" : "1003", "nickname" : "凯撒", "createdatetime" : ISODate("2019-08-06T11:01:02.521Z"), "likenum" : 3000, "state" : "1" } { "_id" : ObjectId("61caf68a54e9b311a0c64dcd"), "content" : "测试添加的数据", "userid" : "1003", "nickname" : "凯撒大帝", "createdatetime" : ISODate("2021-12-28T11:35:38.708Z"), "likenum" : 0, "replynum" : 0, "state" : "1", "articleid" : "100000", "_class" : "cn.itcast.article.po.Comment" } { "_id" : ObjectId("61caf8331858feb3b54d3f74"), "content" : "你年轻,。。。。", "userid" : "1003", "nickname" : "liar", "articleid" : "100001", "parentid" : 3 } { "_id" : ObjectId("61caf92c1858feb3b54d3f76"), "content" : "你真年轻。。。。。", "userid" : "1003", "nickname" : "liar", "articleid" : "100001", "parentid" : "3" }
提示:
这里可能出现错误,说是太多的用户正在认证了。因为我们确实连续登录了两个用户了。
解决方案:退出shell,重新进来登录认证。
2)连接时直接认证
对admin数据库进行登录认证和相关操作:
[root@liar ~]# /usr/local/mongodb/bin/mongo --host=120.79.157.129 --port=27017 --authenticationDatabase admin -u myroot -p 123456 MongoDB shell version v4.4.11-rc1 connecting to: mongodb://120.79.157.129:27017/?authSource=admin&compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("c99891db-055e-4397-b5e1-5b48c34f344d") } MongoDB server version: 4.4.11-rc1 --- The server generated these startup warnings when booting: 2021-12-29T22:24:19.613+08:00: You are running this process as the root user, which is not recommended 2021-12-29T22:24:19.613+08:00: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. We suggest setting it to 'never' --- --- Enable MongoDB's free cloud-based monitoring service, which will then receive and display metrics about your deployment (disk utilization, CPU, operation statistics, etc). The monitoring data will be available on a MongoDB website with a unique URL accessible to you and anyone you share the URL with. MongoDB may use this information to make product improvements and to suggest MongoDB products and deployment options to you. To enable free monitoring, run the following command: db.enableFreeMonitoring() To permanently disable this reminder, run the following command: db.disableFreeMonitoring() --- > show dbs admin 0.000GB articledb 0.000GB config 0.000GB local 0.000GB test 0.000GB
对articledb数据库进行登录认证和相关操作:
[root@liar ~]# /usr/local/mongodb/bin/mongo --host=120.79.157.129 --port=27017 --authenticationDatabase articledb -u common -p 123456
MongoDB shell version v4.4.11-rc1
connecting to: mongodb://120.79.157.129:27017/?authSource=articledb&compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("4084f100-6e53-4940-b25f-8b7540886986") }
MongoDB server version: 4.4.11-rc1
> use articledb
switched to db articledb
> db.comment.find()
-u :用户名
-p :密码
–authenticationDatabase :指定连接到哪个库。当登录是指定用户名密码时,必须指定对应的数据库!
使用用户名和密码连接到 MongoDB 服务器,你必须使用’username:password@hostname/dbname’ 格式,'username’为用户
名,‘password’ 为密码。
目标:使用用户common使用密码 123456 连接到MongoDB 服务上。
application.yml:
spring: #数据源配置 data: mongodb: # 主机地址 # host: 120.79.157.129 # 数据库 # database: articledb # 默认端口是27017 # port: 27017 #帐号 # username: common #密码 # password: 123456 #单机有认证的情况下,也使用字符串连接 uri: mongodb://common:123456@120.79.157.129:27017/articledb
提示:
分别测试用户名密码正确以及不正确的情况。
对于搭建好的mongodb副本集,为了安全,启动安全认证,使用账号密码登录。
副本集环境使用之前搭建好的,架构如下:
对副本集执行访问控制需要配置两个方面:
1)副本集和共享集群的各个节点成员之间使用内部身份验证,可以使用密钥文件或x.509证书。密钥文件比较简单,本文使用密钥文件,官方推荐如果是测试环境可以使用密钥文件,但是正式环境,官方推荐x.509证书。原理就是,集群中每一个实例彼此连接的时候都检验彼此使用的证书的内容是否相同。
只有证书相同的实例彼此才可以访问
2)使用客户端连接到mongodb集群时,开启访问授权。对于集群外部的访问。如通过可视化客户端,或者通过代码连接的时候,需要开启授权。在keyfile身份验证中,副本集中的每个mongod实例都使用keyfile的内容作为共享密码,只有具有正确密钥文件的mongod或者mongos实例可以连接到副本集。密钥文件的内容必须在6到1024个字符之间,并且在unix/linux系统中文件所有者必须有对文件至少有读的权限。
增加副本集的安全认证和服务鉴权功能,可以在副本集搭建的时候直接添加,也可以在之前搭建好的副本集服务上添加。
使用之前搭建好的副本集服务,因此,先停止之前的集群服务停止服务的方式有两种:快速关闭和标准关闭,下面依次说明:
(1)快速关闭方法(快速,简单,数据可能会出错)
目标:通过系统的kill命令直接杀死进程:
依次杀死仲裁者、副本节点、主节点,直到所有成员都离线。建议主节点最后kill,以避免潜在的回滚。
杀完要检查一下,避免有的没有杀掉。
#通过进程编号关闭节点
kill -2 进程编号
【补充】
如果一旦是因为数据损坏,则需要进行如下操作(了解):
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
(2)标准的关闭方法(数据不容易出错,但麻烦):
目标:通过mongo客户端中的shutdownServer命令来依次关闭各个服务
关闭副本集中的服务,建议依次关闭仲裁节点、副本节点、主节点。主要的操作步骤参考如下:
//客户端登录服务,注意,这里通过localhost登录,如果需要远程登录,必须先登录认证才行。
mongo --port 27017
//告知副本集说本机要下线
rs.stepDown()
//#切换到admin库
use admin
//关闭服务
db.shutdownServer()
只需要在主节点上添加用户,副本集会自动同步。
开启认证之前,创建超管用户:myroot,密码:123456
myrs:PRIMARY> use admin
switched to db admin
myrs:PRIMARY> db.createUser({user:"myroot",pwd:"123456",roles:["root"]})
Successfully added user: { "user" : "myroot", "roles" : [ "root" ] }
详细操作详见单实例环境的 添加用户和权限 的相关操作。
提示:
该步骤也可以在开启认证之后,但需要通过localhost登录才允许添加用户,用户数据也会自动同步到副本集。
后续再创建其他用户,都可以使用该超管用户创建。
第一步:生成一个key文件到当前文件夹中。
可以使用任何方法生成密钥文件。例如,以下操作使用openssl生成密码文件,然后使用chmod来更改文件权限,仅为文件所有者提供读取权限
[root@commonhost ~]# openssl rand -base64 90 -out ./mongo.keyfile
[root@commonhost ~]# chmod 400 ./mongo.keyfile
[root@commonhost ~]# ll mongo.keyfile
-r--------. 1 root root 122 8月 14 14:23 mongo.keyfile
提示:
所有副本集节点都必须要用同一份keyfile,一般是在一台机器上生成,然后拷贝到其他机器上,且必须有读的权限,否则将来会报错: permissions on
/mongodb/replica_sets/myrs_27017/mongo.keyfile are too open
一定要保证密钥文件一致,文件位置随便。但是为了方便查找,建议每台机器都放到一个固定的位置,都放到和配置文件一起的目录中。
这里将该文件分别拷贝到多个目录中:
[root@commonhost ~]# cp mongo.keyfile /mongodb/replica_sets/myrs_27017
[root@commonhost ~]# cp mongo.keyfile /mongodb/replica_sets/myrs_27018
[root@commonhost ~]# cp mongo.keyfile /mongodb/replica_sets/myrs_27019
分别编辑几个服务的mongod.conf文件,添加相关内容:
/mongodb/replica_sets/myrs_27017/mongod.conf
security:
#KeyFile鉴权文件
keyFile: /mongodb/replica_sets/myrs_27017/mongo.keyfile
#开启认证方式运行
authorization: enabled
/mongodb/replica_sets/myrs_27018/mongod.conf
security:
#KeyFile鉴权文件
keyFile: /mongodb/replica_sets/myrs_27018/mongo.keyfile
#开启认证方式运行
authorization: enabled
/mongodb/replica_sets/myrs_27019/mongod.conf
security:
#KeyFile鉴权文件
keyFile: /mongodb/replica_sets/myrs_27019/mongo.keyfile
#开启认证方式运行
authorization: enabled
如果副本集是开启状态,则先分别关闭关闭复本集中的每个mongod,从次节点开始。直到副本集的所有成员都离线,包括任何仲裁者。主节点必须是最后一个成员关闭以避免潜在的回滚。
#通过进程编号关闭三个节点
kill -2 进程编号 进程编号 进程编号
分别启动副本集节点:
/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
查看进程情况:
[root@commonhost replica_sets]# ps -ef |grep mongod.conf
#先用管理员账号登录
#切换到admin库
use admin
#管理员账号认证
db.auth("myroot","123456")
#切换到要认证的库
use articledb
#添加普通用户
db.createUser({user: "common", pwd: "123456", roles: ["readWrite"]})
重新连接,使用普通用户common重新登录,查看数据。
注意:也要使用rs.status()命令查看副本集是否健康。
使用用户名和密码连接到 MongoDB 服务器,你必须使用
‘username:password@hostname/dbname’ 格式,'username’为用户名,‘password’ 为密码。
目标:使用用户common使用密码 123456 连接到MongoDB 服务上。
application.yml:
spring:
#数据源配置
data:
mongodb:
#副本集有认证的情况下,字符串连接
uri:mongodb://common:123456@120.79.157.129:27017,120.79.157.129:27018,120.79.157.129:27019/articledb?connect=replicaSet&slaveOk=true&replicaSet=myrs
分片集群环境下的安全认证和副本集环境下基本上一样。
但分片集群的服务器环境和架构较为复杂,建议在搭建分片集群的时候,直接加入安全认证和服务器间的鉴权,如果之前有数据,可先将之前的数据备份出来,再还原回去。本文使用之前搭建好的集群服务,因此,先停止之前的集群服务
停止服务的方式有两种:快速关闭和标准关闭,下面依次说明:
(1)快速关闭方法(快速,简单,数据可能会出错)
目标:通过系统的kill命令直接杀死进程:
#先用管理员账号登录
#切换到admin库
use admin
#管理员账号认证
db.auth("myroot","123456")
#切换到要认证的库
use articledb
#添加普通用户
db.createUser({user: "common", pwd: "123456", roles: ["readWrite"]})
spring:
#数据源配置
data:
mongodb:
#副本集有认证的情况下,字符串连接
uri:mongodb://common:123456@120.79.157.129:27017,120.79.157.129:27018,120.79.157.129:27019/articledb?connect=replicaSet&slaveOk=true&replicaSet=myrs
依次杀死mongos路由、配置副本集服务,分片副本集服务,从次节点开始。直到所有成员都离线。副本集杀的时候,建议先杀仲裁者,再杀副本节点,最后是主节点,以避免潜在的回滚。杀完要检查一下,避免有的没有杀掉。
#通过进程编号关闭节点
kill -2 进程编号
【补充】
如果一旦是因为数据损坏,则需要进行如下操作(了解):
1)删除lock文件:
rm -f /mongodb/sharded_cluster/myshardrs01_27018/data/db/*.lock \
/mongodb/sharded_cluster/myshardrs01_27118/data/db/*.lock \
/mongodb/sharded_cluster/myshardrs01_27218/data/db/mongod.lock \
/mongodb/sharded_cluster/myshardrs02_27318/data/db/mongod.lock \
/mongodb/sharded_cluster/myshardrs02_27418/data/db/mongod.lock \
/mongodb/sharded_cluster/myshardrs02_27518/data/db/mongod.lock \
/mongodb/sharded_cluster/myconfigrs_27019/data/db/mongod.lock \
/mongodb/sharded_cluster/myconfigrs_27119/data/db/mongod.lock \
/mongodb/sharded_cluster/myconfigrs_27219/data/db/mongod.lock
2)依次修复数据:
/usr/local/mongodb/bin/mongod --repair --dbpath=/mongodb/sharded_cluster/myshardrs01_27018/data/db
/usr/local/mongodb/bin/mongod --repair --dbpath=/mongodb/sharded_cluster/myshardrs01_27118/data/db
/usr/local/mongodb/bin/mongod --repair --dbpath=/mongodb/sharded_cluster/myshardrs01_27218/data/db
/usr/local/mongodb/bin/mongod --repair --dbpath=/mongodb/sharded_cluster/myshardrs02_27318/data/db
/usr/local/mongodb/bin/mongod --repair --dbpath=/mongodb/sharded_cluster/myshardrs02_27418/data/db
/usr/local/mongodb/bin/mongod --repair --dbpath=/mongodb/sharded_cluster/myshardrs02_27518/data/db
/usr/local/mongodb/bin/mongod --repair --dbpath=/mongodb/sharded_cluster/myconfigrs_27019/data/db
/usr/local/mongodb/bin/mongod --repair --dbpath=/mongodb/sharded_cluster/myconfigrs_27119/data/db
/usr/local/mongodb/bin/mongod --repair --dbpath=/mongodb/sharded_cluster/myconfigrs_27219/data/db
/usr/local/mongodb/bin/mongod --repair --dbpath=/mongodb/sharded_cluster/mymongos_27017/data/db
/usr/local/mongodb/bin/mongod --repair --dbpath=/mongodb/sharded_cluster/mymongos_27117/data/db
(2)标准的关闭方法(数据不容易出错,但麻烦):
目标:通过mongo客户端中的shutdownServer命令来依次关闭各个服务关闭分片服务器副本集中的服务,建议依次关闭仲裁节点、副本节点、主节点。主要的操作步骤参考如
下:
//客户端登录服务,注意,这里通过localhost登录,如果需要远程登录,必须先登录认证才行。
mongo --port 27018
//告知副本集说本机要下线
rs.stepDown()
//#切换到admin库
use admin
//关闭服务
db.shutdownServer()
关闭配置服务器副本集的服务,建议依次关闭副本节点、主节点。主要的操作步骤参考如下:
//客户端登录服务,注意,这里通过localhost登录,如果需要远程登录,必须先登录认证才行。
mongo --port 27019
//告知副本集说本机要下线
rs.stepDown()
//#切换到admin库
use admin
//关闭服务
db.shutdownServer()
关闭路由服务器的服务,建议依次关闭两个路由节点。主要的操作步骤参考如下:
//客户端登录服务,注意,这里通过localhost登录,如果需要远程登录,必须先登录认证才行。
mongo --port 27017
//告知副本集说本机要下线
rs.stepDown()
//#切换到admin库
use admin
//关闭服务
db.shutdownServer()
第一步:生成一个key文件到当前文件夹中。
可以使用任何方法生成密钥文件。例如,以下操作使用openssl生成密码文件,然后使用chmod来更改
文件权限,仅为文件所有者提供读取权限
[root@commonhost ~]# openssl rand -base64 90 -out ./mongo.keyfile
[root@commonhost ~]# chmod 400 ./mongo.keyfile
[root@commonhost ~]# ll mongo.keyfile
-r--------. 1 root root 122 8月 14 14:23 mongo.keyfile
提示:
所有副本集节点都必须要用同一份keyfile,一般是在一台机器上生成,然后拷贝到其他机器上,且必须有读的权限,否则将来会报错: permissions on
/mongodb/replica_sets/myrs_27017/mongo.keyfile are too open
一定要保证密钥文件一致,文件位置随便。但是为了方便查找,建议每台机器都放到一个固定的位置,
都放到和配置文件一起的目录中。
这里将该文件分别拷贝到多个目录中:
echo '/mongodb/sharded_cluster/myshardrs01_27018/mongo.keyfile
/mongodb/sharded_cluster/myshardrs01_27118/mongo.keyfile
/mongodb/sharded_cluster/myshardrs01_27218/mongo.keyfile
/mongodb/sharded_cluster/myshardrs02_27318/mongo.keyfile
/mongodb/sharded_cluster/myshardrs02_27418/mongo.keyfile
/mongodb/sharded_cluster/myshardrs02_27518/mongo.keyfile
/mongodb/sharded_cluster/myconfigrs_27019/mongo.keyfile
/mongodb/sharded_cluster/myconfigrs_27119/mongo.keyfile
/mongodb/sharded_cluster/myconfigrs_27219/mongo.keyfile
/mongodb/sharded_cluster/mymongos_27017/mongo.keyfile
/mongodb/sharded_cluster/mymongos_27117/mongo.keyfile' | xargs -n 1 cp -v /root/mongo.keyfile
分别编辑几个服务的mongod.conf文件,添加相关内容:
/mongodb/sharded_cluster/myshardrs01_27018/mongod.conf
security:
#KeyFile鉴权文件
keyFile: /mongodb/sharded_cluster/myshardrs01_27018/mongo.keyfile
#开启认证方式运行
authorization: enabled
/mongodb/sharded_cluster/myshardrs01_27118/mongod.conf
security:
#KeyFile鉴权文件
keyFile: /mongodb/sharded_cluster/myshardrs01_27118/mongo.keyfile
#开启认证方式运行
authorization: enabled
/mongodb/sharded_cluster/myshardrs01_27218/mongod.conf
security:
#KeyFile鉴权文件
keyFile: /mongodb/sharded_cluster/myshardrs01_27218/mongo.keyfile
#开启认证方式运行
authorization: enabled
/mongodb/sharded_cluster/myshardrs02_27318/mongod.conf
security:
#KeyFile鉴权文件
keyFile: /mongodb/sharded_cluster/myshardrs02_27318/mongo.keyfile
#开启认证方式运行
authorization: enabled
/mongodb/sharded_cluster/myshardrs02_27418/mongod.conf
security:
#KeyFile鉴权文件
keyFile: /mongodb/sharded_cluster/myshardrs02_27418/mongo.keyfile
#开启认证方式运行
authorization: enabled
/mongodb/sharded_cluster/myshardrs02_27518/mongod.conf
security:
#KeyFile鉴权文件
keyFile: /mongodb/sharded_cluster/myshardrs02_27518/mongo.keyfile
#开启认证方式运行
authorization: enabled
/mongodb/sharded_cluster/myconfigrs_27019/mongod.conf
security:
#KeyFile鉴权文件
keyFile: /mongodb/sharded_cluster/myconfigrs_27019/mongo.keyfile
#开启认证方式运行
authorization: enabled
/mongodb/sharded_cluster/myconfigrs_27119/mongod.conf
security:
#KeyFile鉴权文件
keyFile: /mongodb/sharded_cluster/myconfigrs_27119/mongo.keyfile
#开启认证方式运行
authorization: enabled
/mongodb/sharded_cluster/myconfigrs_27219/mongod.conf
security:
#KeyFile鉴权文件
keyFile: /mongodb/sharded_cluster/myconfigrs_27219/mongo.keyfile
#开启认证方式运行
authorization: enabled
/mongodb/sharded_cluster/mymongos_27017/mongos.conf
security:
#KeyFile鉴权文件
keyFile: /mongodb/sharded_cluster/mymongos_27017/mongo.keyfile
/mongodb/sharded_cluster/mymongos_27117/mongos.conf
security:
#KeyFile鉴权文件
keyFile: /mongodb/sharded_cluster/mymongos_27117/mongo.keyfile
mongos比mongod少了authorization:enabled的配置。原因是,副本集加分片的安全认证需要配置两方面的,副本集各个节点之间使用内部身份验证,用于内部各个mongo实例的通信,只有相同keyfile才能相互访问。所以都要开启 keyFile:
/mongodb/sharded_cluster/mymongos_27117/mongo.keyfile 。
然而对于所有的mongod,才是真正的保存数据的分片。mongos只做路由,不保存数据。所以所有的
mongod开启访问数据的授权authorization:enabled。这样用户只有账号密码正确才能访问到数据。
必须依次启动配置节点、分片节点、路由节点:
/usr/local/mongodb/bin/mongod -f /mongodb/sharded_cluster/myconfigrs_27019/mongod.conf
/usr/local/mongodb/bin/mongod -f /mongodb/sharded_cluster/myconfigrs_27119/mongod.conf
/usr/local/mongodb/bin/mongod -f /mongodb/sharded_cluster/myconfigrs_27219/mongod.conf
/usr/local/mongodb/bin/mongod -f /mongodb/sharded_cluster/myshardrs01_27018/mongod.conf
/usr/local/mongodb/bin/mongod -f /mongodb/sharded_cluster/myshardrs01_27118/mongod.conf
/usr/local/mongodb/bin/mongod -f /mongodb/sharded_cluster/myshardrs01_27218/mongod.conf
/usr/local/mongodb/bin/mongod -f /mongodb/sharded_cluster/myshardrs02_27318/mongod.conf
/usr/local/mongodb/bin/mongod -f /mongodb/sharded_cluster/myshardrs02_27418/mongod.conf
/usr/local/mongodb/bin/mongod -f /mongodb/sharded_cluster/myshardrs02_27518/mongod.conf
/usr/local/mongodb/bin/mongos -f /mongodb/sharded_cluster/mymongos_27017/mongos.conf
/usr/local/mongodb/bin/mongos -f /mongodb/sharded_cluster/mymongos_27117/mongos.conf
注意:
这里有个非常特别的情况,就是启动顺序。先启动配置节点,再启动分片节点,最后启动路由节点。
如果先启动分片节点,会卡住,提示:
about to fork child process, waiting until server is ready for connections
这也许是个bug。原因未知。
客户端mongo,通过localhost登录任意一个mongos路由,
[root@commonhost db]# /usr/local/mongodb/bin/mongo --port 27017
提示:相当于一个后门,只能在admin下添加用户。
创建一个管理员帐号:
mongos> use admin
switched to db admin
mongos> db.createUser({user:"myroot",pwd:"123456",roles:["root"]})
Successfully added user: { "user" : "myroot", "roles" : [ "root" ] }
提示:如果在开启认证之前已经创建了管理员账号,这里可以忽略
创建一个普通权限帐号:
mongos> use admin
switched to db admin
mongos> db.auth("myroot","123456")
1
mongos> use articledb
switched to db articledb
mongos> db.createUser({user: "common", pwd: "123456", roles: [{ role: "readWrite",db: "articledb" }]})
mongos> db.auth("common","123456")
1
提示:
通过mongos添加的账号信息,只会保存到配置节点的服务中,具体的数据节点不保存账号信息,因此,分片中的账号信息不涉及到同步问题。
mongo客户端登录mongos路由,用管理员帐号登录可查看分片情况:
mongos> use admin
switched to db admin
mongos> db.auth("myroot","123456")
1
mongos> sh.status()
退出连接,重新连接服务,使用普通权限帐号访问数据:
[root@commonhost db]# /usr/local/mongodb/bin/mongo --host 120.79.157.129 --port 27017
MongoDB shell version v4.0.10
connecting to: mongodb://120.79.157.129:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("6f84fa91-2414-407e-b3ab-c0b7eedde825")
}
MongoDB server version: 4.0.10
mongos> use articledb
switched to db articledb
mongos> db.auth("common","123456")
1
mongos> show collections
comment
comment2
mongos> db.comment.count()
10001
使用用户名和密码连接到 MongoDB 服务器,你必须使用
‘username:password@hostname/dbname’ 格式,'username’为用户名,‘password’ 为密码。
目标:使用用户common使用密码 123456 连接到MongoDB 服务上。
application.yml:
spring:
#数据源配置
data:
mongodb:
# 分片集群有认证的情况下,字符串连接
uri: mongodb://common:123456@120.79.157.129:27017,120.79.157.129:27117/articledb
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。