MongoDB學習筆記(六)——MongoDB配置使用者賬號與訪問控制
前面的幾篇博文,大概介紹瞭如何安裝MongoDB,以及介紹了MongoDB shell與MongoDB Compass。
新安裝的MongoDB是沒有賬號設定的,也就是說任何人都可以連線進MongoDB,這是非常不安全的。所以我們需要對MongoDB進行設定賬號,來控制對資料庫的訪問。
admin資料庫
admin資料庫是MongoDB安裝時就會自動建立的,如下圖,是我用MongoDB Compass 連線本地新安裝的MongoDB:
大家可以從上面看到,新安裝的MongoDB預設建立三個資料庫,admin、config、local.
- config資料庫暫時不知道用處,如果誰知道,忘告知。
- local資料庫內部有一個startup_log的集合,內部儲存了連線MongoDB的記錄資訊。
對於admin資料庫,這是一個比較特殊的資料庫,具有一些普通資料庫沒有的功能,比如有些使用者賬號被賦予能夠操作對個數據庫的許可權,這些角色就只能在admin中建立,比如能夠操作所有資料庫的超級使用者,當然普通資料庫也可以建立使用者,但是普通資料庫建立的使用者只能用於建立使用者的資料庫。當連線驗證使用者的時候,MongoDB會從指定資料庫的使用者與admin的使用者檢查使用者資訊。
管理使用者賬號
管理使用者賬號,也就是新增、刪除、配置使用者記錄。我們可以通過MongoDB shell 和 MongoDB Compass來操作,當然為了鍛鍊對MongoDB shell的熟悉,建議大家使用MongoDB shell。
- 建立使用者賬號
在建立使用者前,我們使用createUser(user,writeConcern),該方法以前是addUser(),但是已經不能用了,使用createUser()代替。
(注:本博文的createUser適合版本較高,可能低版本的一些欄位都無效了,這裡就不在寫了)
其中user的文件定義如下:
{
user: "<name>",
pwd: "<cleartext password>",
customData: { <any information> },
roles: [
{ role: "<role>" , db: "<database>" } | "<role>",
...
],
authenticationRestrictions: [
{
clientSource: ["<IP>" | "<CIDR range>", ...]
serverAddress: ["<IP>" | "<CIDR range>", ...]
},
...
]
}
writeConcern:該文件是該操作的關注等級(更多可以檢視官方解釋)
- w選項:允許的值分別是 1、0、大於1的值、”majority”、;
- j選項:確保mongod例項寫資料到磁碟上的journal(日誌),這可以確保mongd以外關閉不會丟失資料。設定true啟用。
- wtimeout:指定一個時間限制,以毫秒為單位。wtimeout只適用於w值大於1。
建立使用者所需欄位
欄位 | 格式 | 描述 |
---|---|---|
user | 字串 | 獨一無二的使用者名稱 |
roles | 陣列 | 一個使用者的角色陣列,MongoDB提供了大量可以分配的角色,詳細可見下方的表格 |
pwd | 字串 | 可選,賬號密碼,該欄位可以是雜湊值或字串,不過儲存是按照雜湊值的方式儲存的 |
customData | 任何資料 | 可選的。可以為任意資訊。此欄位可用於儲存管理員希望與此特定使用者關聯的任何資料。例如,這可能是使用者的全名或僱員id |
authenticationRestrictions | array | 可選的。該欄位為3.6版本以後的新特性,伺服器在建立使用者上強制執行的身份驗證限制。指定可連線伺服器的訪問使用者的ip地址列表或指定可連線伺服器的伺服器ip地址列表。(即白名單驗證) |
authenticationRestrictions
欄位名稱 | 資料型別 | 描述 |
---|---|---|
clientSource | ip地址陣列或CIDR範圍 | 如果存在,則伺服器驗證客戶端的ip地址是否位於給定列表中,或者屬於列表中的一個CIDR範圍。如果客戶端的ip地址不在當前,伺服器就不會對使用者進行身份驗證。 |
serverAddress | ip地址陣列或CIDR範圍 | 客戶端可以連線的ip地址列表或CIDR範圍。如果存在,伺服器將驗證客戶端的連線是否符合給定列表中的ip地址列表或CIDR。如果不符合,則伺服器不會對使用者進行身份驗證 |
簡單來說,clientSource 就是伺服器針對客戶端的IP 做白名單控制。serverAddress 就是客戶端針對服務端的IP 做白名單控制。也就是說,客戶端和伺服器端都可以維護一個白名單進行限制。
注:如果使用者繼承了具有不相容身份驗證限制的多個角色,則該使用者將無法使用。例如,如果使用者繼承一個角色的clientSource欄位為[“198.51.100.0”]和另一個clientSource欄位為[“203.0.113.0”]的角色,伺服器無法對使用者進行身份驗證。
可分配的使用者賬號角色
更多可檢視官方文件
角色 | 描述 |
---|---|
read | 讓使用者能夠讀取當前資料庫中的任何集合的資料 |
readAnyDatabase | 和read一樣能夠讀取任何集合的資料,不過該使用者可以讀取任何資料庫的,不在是指定資料庫 |
readWrite | 使用者可以讀寫當前資料庫中的任何集合,讀寫包括插入、刪除、更新文件以及建立、重新命名、刪除集合 |
readWriteAnyDatabase | 與readWrite許可權一樣,不過其可以操作所有資料庫,不再只能操作指定資料庫 |
dbAdmin | 讓使用者能夠讀寫當前資料庫以及清理、修改、壓縮、獲取統計資訊和執行檢查 |
dbAdminAnyDatabase | 與dbAdmin許可權一樣,不過其可以操作所有資料庫,不再只能操作指定資料庫 |
dbOwner | 資料庫所有者可以在資料庫上執行任何管理操作。這個角色結合readWrite、dbAdmin、userAdmin |
clusterManager | 3.4版本以後新特性,提供叢集的管理和監視操作。具有此角色的使用者可以訪問、配置和訪問本地資料庫,它們分別用於分片和複製中。 |
clusterMonitor | 3.4版本新特性,提供對監視工具的只讀訪問許可權,比如MongoDB Cloud Manager和Ops Manager |
hostManager | 提供監視和管理伺服器的能力。 |
clusterAdmin | 讓使用者能夠管理MongoDB,包括連線、叢集、複製、列出資料庫、建立資料庫、和刪除資料庫 |
userAdmin | 讓使用者能夠在當前資料庫中建立和修改使用者賬戶 |
userAdminAnyDatabase | 與userAdmin相同,過其可以操作所有資料庫,不再只能操作指定資料庫 |
backup | 3.4新特性,提供備份資料所需的最小許可權。該角色有足夠的許可權使用MongoDB Cloud Manager、Ops Manager的備用代理或者使用mongodump |
restore | 3.6新特性,提供對非系統集合的轉換。提供從備份中恢復資料所需的特權,這些備份不會對資料進行重新配置。當還原資料時,此角色足夠。 |
root | 提供對所有資源的訪問許可權。集合了readWriteAnyDatabase、dbAdminAnyDatabase、userAdminAnyDatabase、clusterAdmin、backup這些角色的所有許可權。 |
__system | mongodb將此角色分配給表示叢集成員的使用者物件,該角色賦予其持有者對資料庫中的任何物件採取任何操作。請將此角色用於代表應用程式或管理員的使用者物件,而不是在異常情況下。 |
上述的使用者角色表中,每個使用者可以擁有多個角色,即使用者可以同時擁有dbAdmin也可以擁有userAdmin
瞭解了建立使用者所需欄位,以及角色的許可權,那麼我們就可以建立使用者了
連線到mongooDB shell之後,預設連線的是test資料庫,為了演示方便我們,將當前資料庫切換到一個專門用於測試使用者賬號的資料庫,名字隨便取,如下圖所示,切換到了userTest資料庫:
上圖的userTest資料庫原本是沒有的,我們使用use database
命令,會切換到該資料庫,如果該資料庫不存在則會建立,並切換到該資料庫,當然如果該資料庫建立完成之後,內部沒有新增任何的集合,我們使用show dbs
命令,是不會顯示的。
切換到useTest,之後我們使用createUser()方法新增一個測試使用者,如(注:使用shell輸入的時候一定要特別小心,因為坑爹的是shell不能複製貼上,如果報錯,還沒有輸入記錄,只能重新輸入):
use userTest
db.createUser( { user: "test",
pwd: "test",
customData: { employeeId: 12345 },
roles: [ "readWrite"] },
{ w: "majority" , wtimeout: 5000 } )
我們建立完一個使用者後,可以使用show users
或者使用db.getUser(username),db.getUsers()
來檢視當前資料庫的所有使用者。如圖,我們可以看到我們在設定角色是,若未指定資料庫,則其預設當前資料庫。
為了演示,我們可以建立另一個比較複雜的使用者,我們在userTest資料庫中建立一個具有admin資料庫許可權的使用者,
use userTest
db.createUser( { user: "test1",
pwd: "test1",
roles: [{ role: "readAnyDatabase", db: "admin" },
"readWrite"] } )
可以看到現在userTest有兩個使用者了,新建的使用者具有對admin資料庫的讀取所有資料庫的許可權。但是如果我們切換到admin資料庫,是看不到該使用者的,因為這個使用者是資料userTest的,如圖:
當然我們還可以建立一個沒有許可權的使用者,比如:
db.createUser( { user: "test2",
pwd: "test2",
roles: [] } )
建立需要身份驗證白名單的使用者:
db.createUser(
{
user: "test3",
pwd: "test3",
roles: [ ],
authenticationRestrictions: [ {
clientSource: ["192.0.2.0"],
serverAddress: ["198.51.100.0"]
} ]
}
)
如下圖,檢視使用者時,發現ip限制並沒有展示:
這個可能是MongoDB的一個疏忽了。
修改使用者賬號
對於使用者的賬號的修改維護,MongoDB提供了一些方法,由於方法都比較簡單,我這裡就不做演示了,下表為方法列表:
方法 | 描述 |
---|---|
db.changeUserPassword(username, password) | 修改使用者的密碼 |
db.grantRolesToUser(username, roles, writeConcern) | 授權使用者角色列表 |
db.revokeRolesFromUser( username, [ roles ], { writeConcern } ) | 移除一個使用者的一個或多個角色 |
db.updateRole(rolename, update, writeConcern) | 更新使用者定義的角色。該方法必須執行在角色的資料庫上。該方法會完全覆蓋原來的角色配置,如果想要修改某一部分,可以使用角色管理的方法,下篇博文用於介紹MongoDB shell的所有方法 |
刪除使用者
刪除使用者,MongoDB提供了三個方法,
- db.removeUser(username):這個方法是2.6版本以前的刪除使用者的方法,2.6版本以後不建議使用,雖然該方法也能夠刪除使用者,但會報不建議使用的警告。
- db.dropUser(username):這個方法是上個方法的替代方法
- db.dropAllUsers():刪除當前資料的所有使用者
注:刪除某個資料庫的使用者,需要先切換到該資料庫,否則刪除不成功
配置訪問控制
新安裝一個MonoDB資料庫,首先要做的事情,就是新增使用者賬戶配置訪問控制,MongoDB提供了資料庫級的身份驗證和授權,這也就意味著使用者賬戶存在於單個數據庫中,為支援基本的身份驗證,MongoDB在每個資料庫中,都將使用者憑證儲存在admin資料庫的集合system.users中。如果想要查詢system.users中的資料,需要先切換到admin資料庫,然後使用db.admin.users.find()
,如:
建立超級使用者(root)
如果我們開啟資料庫的身份驗證功能,那麼我們首先需要建立一個超級使用者,超級使用者最起碼功能能夠建立使用者,便於能夠登入。
建立超級使用者,我們只需要給它賦予root許可權即可,同樣,和建立普通使用者一致,只不過需要在admin資料庫中建立,如圖:
啟用身份驗證
建立超級管理員之後,我們就可以開啟資料庫的身份驗證了。
很簡單 ,如果是命令列啟動,直接啟動時加--auth
引數即可。
如果是配置檔案啟動,在配置檔案中配置auth=true
即可。
首先我們需要先關閉當前啟動的MongoDB。大家可以參考這篇文章
然後我們修改配置檔案,如圖:
然後使用mongod命令啟動服務,或者使用windows服務啟動,因為我們的服務已經註冊為服務,我們只需要使用net start MongoDB
啟動服務即可,如圖:
上圖啟動成功。
這時候由於開啟了身份驗證,這時候我們連線MongoDB shell後,在操作資料庫的功能,就會提示沒有許可權操作,如圖:
這時候我們需要使用db.auth(username,password)
來驗證身份。驗證之後就可以進行對應角色能夠操作的功能了。
當然我們也可以在連線MongoDB shell時就可以使用 –username 和 –password 來想資料庫校驗身份,命令格式為:
mongo ip:port/database --username "username" -- password "password"
如圖:
注:指定的資料庫必須是賬戶所在的資料庫,否則會報錯,如下圖
如果大家使用MongoDB Compass連線MongoDB,那麼大家就需要輸入使用者名稱密碼,如圖:
我這邊出現這樣的一種情況,資料庫連線進去了,但是在載入導航欄時,報錯,報的是:
An error occurred while loading navigation:there are no users authenticated
說沒有許可權,但是許可權列表中是沒有關於MongoDB Compass的相關許可權的,頂多也就需要個讀寫許可權。但是讀寫許可權我們的許可權是足的。昨天一直報這個連線不上去,也沒找到解決方法,但是,今天早上我清理下電腦快取之後,MongoDB 又能正常連線了。所以我估計是快取垃圾的問題。大家可以嘗試下。
最後注一個想要說的:
如果你在實驗的時候,開啟了身份驗證,但是賬號沒設定、設定角色錯了、密碼賬號忘記等導致登入不進MongoDB,那麼我們有一個解決方法,就是將配置檔案中的許可權驗證給刪除掉,重新登入進MongoDB進行相應的修改,該方法僅供非常緊急的時候的解決方法,但是不建議這樣做。