尚硅谷+黑馬程序員MongoDB視頻學習筆記(三)

本文是根據黑馬程序員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)來管理用戶對實例的訪問。通過對用戶授予一個或多個角色來控制用戶訪問數據庫資源的權限和數據庫操作的權限,在對用戶分配角色之前,用戶無法訪問實例。在實例啓動時添加選項--auth 或指定啓動配置文件中添加選項auth=true 。

2)角色:

在MongoDB中通過角色對用戶授予相應數據庫資源的操作權限,每個角色當中的權限可以顯式指定,也可以通過繼承其他角色的權限,或者兩都都存在的權限。

3)權限:

權限由指定的數據庫資源(resource)以及允許在指定資源上進行的操作(action)組成。

1. 資源(resource)包括:數據庫、集合、部分集合和集羣;

2. 操作(action)包括:對資源進行的增、刪、改、查(CRUD)操作。

在角色定義時可以包含一個或多個已存在的角色,新創建的角色會繼承包含的角色所有的權限。在同一個數據庫中,新創建角色可以繼承其他角色的權限,在admin 數據庫中創建的角色可以繼承在其它任意數據庫中角色的權限。

關於角色權限的查看,可以通過如下命令查詢(瞭解)

// 查詢所有角色權限(僅用戶自定義角色)
> 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>" },
...
]
}
)

 

常用的內置角色:
數據庫用戶角色:read、readWrite;
所有數據庫用戶角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
數據庫管理角色:dbAdmin、dbOwner、userAdmin;
集羣管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;
備份恢復角色:backup、restore;
超級用戶角色:root
內部角色:system

 

角色說明

 

2、創建認證用戶

(1)下面創建兩個管理員用戶,一個是系統的超級管理員myroot ,一個是admin庫的管理用戶

myadmin (注意,在沒有開啓認證的時候,也就是在開啓認證之前添加):

//切換到admin庫
> use admin
//創建系統超級用戶 myroot,設置密碼123456,設置角色root
//> db.createUser({user:"myroot",pwd:"123456",roles:[ { "role" : "root", "db" :
"admin" } ]})
//或
> db.createUser({user:"myroot",pwd:"123456",roles:["root"]})
Successfully added user: { "user" : "myroot", "roles" : [ "root" ] }

//創建專門用來管理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()

//刪除用戶
> db.dropUser("myadmin")
true
> db.system.users.find()
//修改密碼
> db.changeUserPassword("myroot", "123456")

提示:

1)本案例創建了兩個用戶,分別對應超管和專門用來管理用戶的角色,事實上,你只需要一個用戶即可。如果你對安全要求很高,防止超管泄漏,則不要創建超管用戶。

2)和其它數據庫(MySQL)一樣,權限的管理都差不多一樣,也是將用戶和權限信息保存到數據庫對應的表中。Mongodb存儲所有的用戶信息在admin 數據庫的集合system.users中,保存用戶名、密碼和數據庫信息。

3)如果不指定數據庫,則創建的指定的權限的用戶在所有的數據庫上有效,如{role:"userAdminAnyDatabase", db:""}

 

(2)創建普通用戶

創建普通用戶可以在沒有開啓認證的時候添加,也可以在開啓認證之後添加,但開啓認證之後,必須使用有操作admin庫的用戶登錄認證後才能操作。底層都是將用戶信息保存在了admin數據庫的集合system.users中。

//創建(切換)將來要操作的數據庫articledb,
> use articledb
switched to db articledb

//創建用戶,擁有articledb數據庫的讀寫權限readWrite,密碼是123456
> db.createUser({user: "bobo", pwd: "123456", roles: [{ role: "readWrite", db:
"articledb" }]})
//> db.createUser({user: "bobo", pwd: "123456", roles: ["readWrite"]})
Successfully added user: {
"user" : "bobo",
"roles" : [
{
"role" : "readWrite",
"db" : "articledb"
}
]
}

//測試是否可用
> db.auth("bobo","123456")
1

提示:

如果開啓了認證後,登錄的客戶端的用戶必須使用admin庫的角色,比如擁有root角色的myadmin用戶,再通過myadmin用戶去創建其他角色的用戶。

 

3、服務端開啓認證和客戶端連接登錄

(1)停止服務

關閉已經啓動的服務,兩種方式,一是可以使用Linux命令殺掉進程。二是在mongo客戶端中使用shutdownServer命令來關閉。但注意,有以下條件限制:

  • 必須是在admin庫下執行該關閉服務命令。
  • 如果沒有開啓認證,必須是從localhost登陸的,才能執行關閉服務命令。
  • 非localhost的、通過遠程登錄的,必須有登錄且必須登錄用戶有對admin操作權限纔可以。

 

(2)以開啓認證的方式啓動服務

有兩種方式開啓權限認證啓動服務:一種是參數方式,一種是配置文件方式。

參數方式:

在啓動時指定參數--auth,比如:

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

配置文件方式:

在mongodb.conf配置文件中加入:

security:
  #開啓授權認證
  authorization: enabled

啓動時可不加--auth 參數:/usr/local/mongodb/bin/mongod -f /mongodb/single/mongod.conf

 

(3)開啓了認證的情況下的客戶端登陸

有兩種認證方式,一種是先登錄,在mongo shell中認證,比如:db.auth("myroot","123456")

一種是登錄時直接認證。使用這三個參數 -u :用戶名,-p :密碼,--authenticationDatabase :指定連接到哪個庫。當登錄是指定用戶名密碼時,必須指定對應的數據庫!

 

(4)SpringDataMongoDB連接認證

使用用戶名和密碼連接到 MongoDB 服務器,你必須使用

'username:password@hostname/dbname' 格式,'username'爲用戶名,'password' 爲密碼。

目標:使用用戶bobo使用密碼 123456 連接到MongoDB 服務上。

 

4、給副本集羣環境開啓認證服務

(1)副本集認證說明

與單個MongoDB開啓認證服務相比,給副本集羣環境開啓認證服務是類似的,也是要添加認證用戶,但是多了一步操作,就是要創建副本集認證的key文件。

對副本集執行訪問控制需要配置兩個方面:

1)副本集和共享集羣的各個節點成員之間使用內部身份驗證,可以使用密鑰文件或x.509證書。密鑰文件比較簡單,本文使用密鑰文件,官方推薦如果是測試環境可以使用密鑰文件,但是正式環境,官方推薦x.509證書。原理就是,集羣中每一個實例彼此連接的時候都檢驗彼此使用的證書的內容是否相同。只有證書相同的實例彼此纔可以訪問

2)使用客戶端連接到mongodb集羣時,開啓訪問授權。對於集羣外部的訪問。如通過可視化客戶端,或者通過代碼連接的時候,需要開啓授權。

 

在keyfile身份驗證中,副本集中的每個mongod實例都使用keyfile的內容作爲共享密碼,只有具有正確密鑰文件的mongod或者mongos實例可以連接到副本集。密鑰文件的內容必須在6到1024個字符之間,並且在unix/linux系統中文件所有者必須有對文件至少有讀的權限。

 

(2)創建副本集認證的key文件

第一步:生成一個key文件到當前文件夾中。

可以使用任何方法生成密鑰文件。例如,以下操作使用openssl生成密碼文件,然後使用chmod來更改文件權限,僅爲文件所有者提供讀取權限

[root@bobohost ~]# openssl rand -base64 90 -out ./mongo.keyfile
[root@bobohost ~]# chmod 400 ./mongo.keyfile

提示:

所有副本集節點都必須要用同一份keyfile,一般是在一臺機器上生成,然後拷貝到其他機器上,且必須有讀的權限,否則將來會報錯: permissions on

一定要保證密鑰文件一致,文件位置隨便。但是爲了方便查找,建議每臺機器都放到一個固定的位置,都放到和配置文件一起的目錄中。

 

第二步:修改配置文件制定keyfile

分別編輯幾個服務的mongod.conf文件,添加相關內容:

security:
  #KeyFile鑑權文件
  keyFile: /mongodb/replica_sets/myrs_27017/mongo.keyfile
  #開啓認證方式運行
  authorization: enabled

第三步:重啓副本集

 

5、分片集羣環境開啓認證服務

分片集羣環境下的安全認證和副本集環境下基本上一樣。

但分片集羣的服務器環境和架構較爲複雜,建議在搭建分片集羣的時候,直接加入安全認證和服務器間的鑑權,如果之前有數據,可先將之前的數據備份出來,再還原回去。

 

創建認證賬號和創建key文件都一樣,區別在於後面添加到mongos.conf配置文件和mongod.conf配置文件,如下:

mongod.conf:

security:
  #KeyFile鑑權文件
  keyFile: /mongodb/sharded_cluster/myshardrs02_27018/mongo.keyfile
  #開啓認證方式運行
  authorization: enabled

mongos.conf:

security:
  #KeyFile鑑權文件
  keyFile: /mongodb/sharded_cluster/mymongos_27017/mongo.keyfile

mongos比mongod少了authorization:enabled的配置。原因是,副本集加分片的安全認證需要配置兩方面的,副本集各個節點之間使用內部身份驗證,用於內部各個mongo實例的通信,只有相同keyfile才能相互訪問。所以都要開啓keyFile:

/mongodb/sharded_cluster/mymongos_27117/mongo.keyfile

然而對於所有的mongod,纔是真正的保存數據的分片。mongos只做路由,不保存數據。所以所有的mongod開啓訪問數據的授權authorization:enabled。這樣用戶只有賬號密碼正確才能訪問到數據。

 

至此,MongoDB入門已經完成。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章