1. 程式人生 > >MongoDB學習筆記(六)——MongoDB配置使用者賬號與訪問控制

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。

  1. 建立使用者賬號

在建立使用者前,我們使用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進行相應的修改,該方法僅供非常緊急的時候的解決方法,但是不建議這樣做。