對(duì)于一個(gè)完善的數(shù)據(jù)庫(kù)系統(tǒng),必然是需要權(quán)限控制,當(dāng)然MongoDB也不例外.沒(méi)有認(rèn)證的數(shù)據(jù)庫(kù)已經(jīng)被證明是******的一個(gè)突破口,所以我們無(wú)論是出于什么原因,數(shù)據(jù)庫(kù)認(rèn)證對(duì)于一個(gè)生產(chǎn)系統(tǒng)而言,至關(guān)重要.
成都創(chuàng)新互聯(lián)主營(yíng)化德網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營(yíng)網(wǎng)站建設(shè)方案,app開(kāi)發(fā)定制,化德h5重慶小程序開(kāi)發(fā)搭建,化德網(wǎng)站營(yíng)銷(xiāo)推廣歡迎化德等地區(qū)企業(yè)咨詢(xún)
在MongoDB 3.0 以后,用戶(hù)登錄的密碼認(rèn)證機(jī)制有:SCRAM-SHA-1(默認(rèn),基于加鹽的應(yīng)答式認(rèn)證),MONGODB-CR(普通應(yīng)答式認(rèn)證,3.6廢棄,4.0刪除),x.509 Certificate(基于證書(shū)的SSL/TLS加密認(rèn)證),LDAP Proxy(基于LDAP系統(tǒng)的鑒權(quán)認(rèn)證,僅企業(yè)版支持),Kerberos(基于Kerberos鑒權(quán),僅企業(yè)版支持),一般而言,默認(rèn)的就已經(jīng)很不錯(cuò)了.
然后mongodb還有一個(gè)內(nèi)部鑒權(quán)策略,主要是防止數(shù)據(jù)被攔截,有:keyfile(基于SCRAM的應(yīng)答式認(rèn)證),x.509 Certificate(基于證書(shū)的SSL/TLS加密),對(duì)于內(nèi)部來(lái)說(shuō),如非特殊情況,使用keyfile就足夠了.
對(duì)單臺(tái)數(shù)據(jù)庫(kù)增加mongodb認(rèn)證信息(基本認(rèn)證知識(shí))
首先要講一講的是,mongodb本身并沒(méi)有要求一定要認(rèn)證登錄,也就是免認(rèn)證直接登錄是允許的,不過(guò)出于安全考慮的話(huà),我們應(yīng)該更加嚴(yán)謹(jǐn)一些,增加認(rèn)證登錄來(lái)使用,但是mongodb又不同于MySQL和oracle的授權(quán)方式,比較奇怪.下面來(lái)看.
首先,也是要打開(kāi)參數(shù)
#打開(kāi)配置文件 vim /usr/local/mongodb/mongod_data_40001.conf . . . #是否開(kāi)啟認(rèn)證模式,現(xiàn)在開(kāi)啟來(lái)使用 auth = true #關(guān)閉認(rèn)證模式,和上面的沖突,之前是開(kāi)啟的,現(xiàn)在關(guān)閉了 #noauth = true #指定集群認(rèn)證文件,沒(méi)開(kāi)認(rèn)證就不用指定,注釋關(guān)閉即可,需要用openssl來(lái)生成,暫時(shí)不研究 #keyFile = /data/mongodb/data/keyfile #指定訪(fǎng)問(wèn)地址,3.4之前默認(rèn)全網(wǎng),之后則默認(rèn)是127.0.0.1,但是在3.6之后必須制定這個(gè)參數(shù)才能啟動(dòng).配置0.0.0.0代表全網(wǎng)匹配 #bind_ip=0.0.0.0
參數(shù)打開(kāi)了,需要重啟一下登錄
#登錄進(jìn)去操作 mongo -port=40001 MongoDB shell version v3.4.16-rc0 connecting to: mongodb://127.0.0.1:40001/ MongoDB server version: 3.4.16-rc0 #操作一下 > show dbs 2018-07-17×××5:04:34.009+0800 E QUERY [thread1] Error: listDatabases failed:{ "ok" : 0, "errmsg" : "not authorized on admin to execute command { listDatabases: 1.0 }", "code" : 13, "codeName" : "Unauthorized" } : _getErrorWithCode@src/mongo/shell/utils.js:25:13 Mongo.prototype.getDBs@src/mongo/shell/mongo.js:62:1 shellHelper.show@src/mongo/shell/utils.js:788:19 shellHelper@src/mongo/shell/utils.js:678:15 @(shellhelp2):1:1 >
好像報(bào)錯(cuò)了,但是請(qǐng)淡定,這是正?,F(xiàn)象,因?yàn)橹澳J(rèn)是免認(rèn)證,現(xiàn)在開(kāi)啟了認(rèn)證,你又沒(méi)創(chuàng)建用戶(hù),那肯定是報(bào)錯(cuò)的,不過(guò)不用擔(dān)心,因?yàn)槟阍臼菦](méi)用戶(hù)密碼的,所以是可以新建的.
但是要注意,在初始無(wú)賬戶(hù)密碼狀態(tài)下,只能通過(guò)登錄127.0.0.1這個(gè)地址你才能創(chuàng)建用戶(hù)和密碼,所以就需要注意參數(shù)bind_ip的值了.
#進(jìn)入admin數(shù)據(jù)庫(kù),也是當(dāng)前用戶(hù)認(rèn)證庫(kù) > use admin switched to db admin #授權(quán) > db.createUser({user:"adminuser",pwd:"admin123",roles:[{role:"userAdminAnyDatabase",db:"admin"}]}) Successfully added user: { "user" : "adminuser", "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ] } #再創(chuàng)建多一個(gè)試試 > db.createUser({user:"root",pwd:"root123",roles:[{role:"root",db:"admin"}]}) 2018-07-17×××5:05:04.167+0800 E QUERY [thread1] Error: couldn't add user: not authorized on admin to execute command { createUser: "root", pwd: "xxx", roles: [ { role: "root", db: "admin" } ], digestPassword: false, writeConcern: { w: "majority", wtimeout: 600000.0 } } : _getErrorWithCode@src/mongo/shell/utils.js:25:13 DB.prototype.createUser@src/mongo/shell/db.js:1292:15 @(shell):1:1 >
又報(bào)錯(cuò)了?沒(méi)錯(cuò),這個(gè)時(shí)候你已經(jīng)有用戶(hù)了,所以就拒絕你的操作了,你要先認(rèn)證一下你自己剛建好的用戶(hù)了
#認(rèn)證一下你剛才創(chuàng)建的用戶(hù) > db.auth("adminuser","admin123") 1 > use admin switched to db admin #再次創(chuàng)建用戶(hù) > db.createUser({user:"root",pwd:"root123",roles:[{role:"root",db:"admin"}]}) Successfully added user: { "user" : "root", "roles" : [ { "role" : "root", "db" : "admin" } ] } > db.auth("root","root123") 1 > show dbs admin 0.000GB local 0.000GB >
這次沒(méi)問(wèn)題了,解決了問(wèn)題,要想創(chuàng)建更多用戶(hù),甚至細(xì)化到個(gè)別數(shù)據(jù)庫(kù)來(lái)創(chuàng)建用戶(hù),你可以這樣:
use foo; db.createUser({user: 'foo', pwd: 'bar', roles: [{role: 'readWrite', db: 'foo'}]}) db.auth('foo', 'bar')
這里就涉及一個(gè)mongodb特別的知識(shí)點(diǎn)---認(rèn)證庫(kù)的概念.
mongodb和別的數(shù)據(jù)庫(kù)不同,認(rèn)證的信息是細(xì)化到庫(kù)的,而并不是像mysql,oracle,sql server那樣集中管理,都存放到一個(gè)user表.
不同數(shù)據(jù)庫(kù)的用戶(hù)可以存放到不同的數(shù)據(jù)庫(kù),例如:foo庫(kù)的用戶(hù)foo只存放在foo庫(kù)里面,他不能登錄admin庫(kù),在admin庫(kù)里面是沒(méi)有foo用戶(hù)信息.同理,admin庫(kù)的用戶(hù)root是不存在于foo庫(kù)的,但是root用戶(hù)是能登陸foo的,原因是root用戶(hù)的權(quán)限更大一些(廢話(huà)).但是,你如果把foo庫(kù)刪除了,那么foo用戶(hù)也會(huì)"順便"被一起刪除了,也就是這個(gè)用戶(hù)和這個(gè)庫(kù)也徹底不再了.
所以我們有兩種不同的理念,基于方便管理的概念來(lái)說(shuō),我們應(yīng)該集中管理,對(duì)于認(rèn)證庫(kù)這個(gè)概念,我們的思路應(yīng)該把它們都建立在admin庫(kù)更佳,然后再細(xì)分權(quán)限,刪除庫(kù)有時(shí)候可以只是刪除登錄用戶(hù)就可以了.基于安全考慮問(wèn)題,我們不能讓一些廢棄用戶(hù)存在,因?yàn)閙ongodb的特性是沒(méi)有create動(dòng)作,只要有權(quán)限,就可以自動(dòng)創(chuàng)建庫(kù)和表的.
然后還有第二個(gè)mongodb的知識(shí)點(diǎn)---角色權(quán)限管理
mongodb創(chuàng)建的用戶(hù)是按role角色來(lái)區(qū)分權(quán)限的,跟我們熟悉的oracle和sql server相似(mysql8.0后才支持角色管理),這點(diǎn)倒不是特別了.至于有什么role選擇呢,你可以show roles看看.我們主要常用的有全局超級(jí)管理員userAdminAnyDatabase(也是我們第一個(gè)需要?jiǎng)?chuàng)建的用戶(hù)權(quán)限),readWriteAnyDatabase,readWrite,readAnyDatabase,read,root等.
每一個(gè)角色代表著有不同的權(quán)限集合,可以細(xì)化到每個(gè)用戶(hù)的權(quán)限范圍,例如read就只能find查詢(xún),readWrite就是典型的增刪查改了,還有我們熟悉的root就是完全控制權(quán)限了.
mongos> show roles { "role" : "__system", "db" : "admin", "isBuiltin" : true, "roles" : [ ], "inheritedRoles" : [ ] } { "role" : "backup", "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" : [ ] }
這里就不詳細(xì)解析了,大多數(shù)和字面意思差不多,非常贊.
既然創(chuàng)建完成了,我們嘗試下帶用戶(hù)名的登陸方式:
[root@localhost ~]# mongo 10.21.14.16:40001/admin -u root -p "root123" MongoDB shell version v3.4.16-rc0 connecting to: mongodb://10.21.14.16:40001/admin MongoDB server version: 3.4.16-rc0 > show dbs admin 0.000GB local 0.000GB >
可以正常使用了.
當(dāng)然了,用戶(hù)就必須是可以修改和刪除信息的,這里不詳細(xì)講,附上命令參考
#假設(shè)我們新建了一個(gè)用戶(hù)ttt,這里就不解析了 >use admin >db.createUser({user:"ttt",pwd:"123",roles:[{role:"root",db:"admin"}]}) >db.auth("ttt","123") #查看現(xiàn)在所有的用戶(hù)信息,也就多了個(gè)ttt了. > db.system.users.find() { "_id" : "admin.adminuser", "user" : "adminuser", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "jLubKc6ODHMxCnjFeeJuog==", "storedKey" : "l1cL39bnvkw2fecw1DHdKM0TM7s=", "serverKey" : "ZD+EZymr8OhlwMZ/0h35Qn8QHE4=" } }, "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ] } { "_id" : "admin.root", "user" : "root", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "Fx2BRB2ZIJeD2X+bvM0ZIg==", "storedKey" : "Yyo+vcxhv40vNXZwUNfnBTz×××30=", "serverKey" : "th4UbT+/aJcgOXvKx4TFDhX242k=" } }, "roles" : [ { "role" : "root", "db" : "admin" } ] } { "_id" : "admin.ttt", "user" : "ttt", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "X58qg8jiiM3ju8v8Cywu8A==", "storedKey" : "MO4lwHhFUn50Ja0/QCHeN4hObRQ=", "serverKey" : "N9iUXgshDP9beTD8pNKfrmtl0V0=" } }, "roles" : [ { "role" : "root", "db" : "admin" } ] } #另一個(gè)命令也能看到 > db.getUsers() [ { "_id" : "admin.adminuser", "user" : "adminuser", "db" : "admin", "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ] }, { "_id" : "admin.root", "user" : "root", "db" : "admin", "roles" : [ { "role" : "root", "db" : "admin" } ] }, { "_id" : "admin.ttt", "user" : "ttt", "db" : "admin", "roles" : [ { "role" : "root", "db" : "admin" } ] } ] #再看看新建的那個(gè)用戶(hù) > db.getUser("ttt") { "_id" : "admin.ttt", "user" : "ttt", "db" : "admin", "roles" : [ { "role" : "root", "db" : "admin" } ] } #我們修改用戶(hù)的所有信息,都可以通過(guò)下面這條命令實(shí)現(xiàn), #db.updateUser("UESR",{修改信息}) #現(xiàn)在我們需要修改的是密碼 > db.updateUser("ttt",{pwd:"789"}) #修改完成,舊密碼登錄就會(huì)報(bào)錯(cuò) > db.auth("ttt","123") Error: Authentication failed. 0 #新密碼就沒(méi)事了 > db.auth("ttt","789") 1 #不過(guò),修改密碼的方式并不是只有一種,下面這種也行 > db.changeUserPassword("ttt","456") #同理,舊密碼登錄就會(huì)報(bào)錯(cuò)了 > db.auth("ttt","123") Error: Authentication failed. 0 #新密碼就沒(méi)事了 > db.auth("ttt","456") 1 #刪除用戶(hù)就很簡(jiǎn)單了 > db.dropUser("ttt") true #現(xiàn)在你還想登錄,當(dāng)然是不行的 > db.getUser("ttt") 2018-07-18T09:38:38.504+0800 E QUERY [thread1] Error: not authorized on admin to execute command { usersInfo: "ttt" } : _getErrorWithCode@src/mongo/shell/utils.js:25:13 DB.prototype.getUser@src/mongo/shell/db.js:1518:1 @(shell):1:1 #登錄到其他用戶(hù)就行了 > db.auth("root","root123") 1 > db.dropUser("ttt") false > db.getUser("ttt") null > db.getUsers() [ { "_id" : "admin.adminuser", "user" : "adminuser", "db" : "admin", "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ] }, { "_id" : "admin.root", "user" : "root", "db" : "admin", "roles" : [ { "role" : "root", "db" : "admin" } ] } ] >
關(guān)于單臺(tái)服務(wù)器的認(rèn)證方式就說(shuō)到這里了.
對(duì)集群數(shù)據(jù)庫(kù)增加mongodb認(rèn)證信息
正如我之前說(shuō)的,使用mongodb,大部分人不會(huì)只用單臺(tái),因?yàn)檫@就是源生的分布式數(shù)據(jù)庫(kù).而使用集群的認(rèn)證,比起單臺(tái),則需要增加一個(gè)keyfile,當(dāng)然你也能用另一種,這里不展開(kāi)講太多.
我這里前置條件說(shuō)明一下,這個(gè)時(shí)候集群是已經(jīng)搭建好了,但是集群內(nèi)的用戶(hù)還沒(méi)有創(chuàng)建起來(lái),因?yàn)槟銢](méi)有創(chuàng)建keyfile也是走不起來(lái).
首先,要在所有節(jié)點(diǎn)配置都打開(kāi)keyfile,并配上路徑,并確保mongodb有這個(gè)文件的權(quán)限,無(wú)論你是分片集群,還是單純副本集,在mongos端,config端,share端,都要一起啟用,要不然沒(méi)有配置的就會(huì)報(bào)權(quán)限錯(cuò)誤,如果是副本集而又授權(quán)了,你還需要重新做一遍才行.
#打開(kāi)配置文件 vim /usr/local/mongodb/mongod_data_40001.conf . . . #是否開(kāi)啟認(rèn)證模式,現(xiàn)在開(kāi)啟來(lái)使用 auth = true #關(guān)閉認(rèn)證模式,和上面的沖突,之前是開(kāi)啟的,現(xiàn)在關(guān)閉了 #noauth = true #指定集群認(rèn)證文件,沒(méi)開(kāi)認(rèn)證就不用指定,注釋關(guān)閉即可,需要用openssl來(lái)生成,暫時(shí)不研究 keyFile = /data/mongodb/data/keyfile #指定訪(fǎng)問(wèn)地址,3.4之前默認(rèn)全網(wǎng),之后則默認(rèn)是127.0.0.1,但是在3.6之后必須制定這個(gè)參數(shù)才能啟動(dòng).配置0.0.0.0代表全網(wǎng)匹配 #bind_ip=0.0.0.0
改完之后,沒(méi)啟動(dòng)就先不要急著啟動(dòng),而已經(jīng)啟動(dòng)了的,也不要急著重啟,稍等再重啟.
然后,我們要生成這個(gè)keyfile文件
#用openssl命令生成一個(gè)64位的秘鑰文件 openssl rand -base64 64 > keyfile #把它權(quán)限設(shè)成600,不然就報(bào)錯(cuò)權(quán)限過(guò)高的錯(cuò)誤 chmod 600 keyfile #把他移到目的目錄 mv keyfile /data/mongodb/data/ #記得把權(quán)限搞一搞 chown mongodb:mongodb /data/mongodb/data/keyfile
有些人好奇,為什么是64位的秘鑰文件?沒(méi)錯(cuò),真的可以更多,或者更少,例如:
openssl rand -base64 741 >keyfile openssl rand -base64 16 >keyfile
這些都可以用,但是,要考慮系統(tǒng)性能問(wèn)題和數(shù)據(jù)安全的問(wèn)題.秘鑰文件越復(fù)雜,那么你內(nèi)部系統(tǒng)的加密與解密就需要更耗費(fèi)資源,尤其在高并發(fā)環(huán)境,可以講比較悲催.但是太簡(jiǎn)單,那么你的數(shù)據(jù)被破解的幾率就更高,安全性就談不上了.我這里只是折衷,所以是64,各位有興趣可以根據(jù)實(shí)際情況來(lái)設(shè)置.
再然后,重新啟動(dòng)各節(jié)點(diǎn),或者說(shuō)你沒(méi)啟動(dòng)的話(huà),就現(xiàn)在啟動(dòng)了,按以下順序重啟所有服務(wù)
config副本集:先主庫(kù),再?gòu)膸?kù),讓他慢慢切換.
router服務(wù):隨便重啟.
shard副本集:先主庫(kù),再?gòu)膸?kù),讓他慢慢切換.
最后,就開(kāi)始創(chuàng)建用戶(hù)授權(quán)了,就和上面一樣操作就可以了
#如果我們沒(méi)有做好副本集或集群,那就還需要先做,詳細(xì)解析我就不做了. > config = {_id:"sljd_shard1",members:[{_id:0, host:"172.25.40.80:40001" },{_id:1, host:"172.25.40.81:40001" },{_id:2, host:"172.25.40.82:40001" }]} > rs.initiate(config) > rs.status() #然后進(jìn)入admin數(shù)據(jù)庫(kù),也是當(dāng)前用戶(hù)認(rèn)證庫(kù) shard1:PRIMARY> use admin switched to db admin #授權(quán) shard1:PRIMARY> db.createUser({user:"root",pwd:"admin123",roles:[{role:"userAdminAnyDatabase",db:"admin"}]}) Successfully added user: { "user" : "adminuser", "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ] } #然后登陸 shard1:PRIMARY> db.auth("root","admin123") #或者 mongo 172.25.40.80:40001/admin -u root -p "admin123"
然后,我們看到用戶(hù)了
#登陸上主庫(kù),注意認(rèn)證庫(kù) mongo 172.25.40.80:40001/admin -u root -p "admin123" #在主庫(kù)上查看一下用戶(hù)情況 shard1:PRIMARY> db.getUsers() [ { "_id" : "admin.root", "user" : "root", "db" : "admin", "roles" : [ { "role" : "root", "db" : "admin" } ] } ] #登陸上從庫(kù).注意認(rèn)證庫(kù) mongo 172.25.40.81:40001/admin -u root -p "admin123" #要多做一步,允許在從庫(kù)執(zhí)行查詢(xún),不然會(huì)報(bào)錯(cuò),因?yàn)閺膸?kù)默認(rèn)是只讀的 shard1:SECONDARY> rs.slaveOk() #再在從庫(kù)執(zhí)行一下 shard1:SECONDARY> db.getUsers() [ { "_id" : "admin.root", "user" : "root", "db" : "admin", "roles" : [ { "role" : "root", "db" : "admin" } ] } ]
好了,那就沒(méi)問(wèn)題了.
網(wǎng)頁(yè)名稱(chēng):建立mongodb的登錄認(rèn)證功能
本文網(wǎng)址:http://chinadenli.net/article28/pijecp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化、App設(shè)計(jì)、微信小程序、靜態(tài)網(wǎng)站、域名注冊(cè)、網(wǎng)站營(yíng)銷(xiāo)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)