mongod 關鍵字參數:--auth
默認值是不需要驗證,即 --noauth,該參數啟用用戶訪問權限控制;當mongod 使用該參數啟動時,MongoDB會驗證客戶端連接的賬戶和密碼,以確定其是否有訪問的權限。如果認證不通過,那么客戶端不能訪問MongoDB的數據庫。
這個參數我們可以寫在配置文件中,表示每次啟動服務都打開auth認證,在這里我們是加在了mongod的啟動指令中,如下所示
[root@:vg_adn_tidbCkhsTest /usr/local/mongodb]#bin/mongo -u "admin" -p "123456" --authenticationDatabase "admin" MongoDB shell version v3.4.18 connecting to: mongodb://127.0.0.1:27017 MongoDB server version: 3.4.18 > db test
這里的“admin”數據庫是我們在安裝mongo的時候就已經創建的,並且在數據庫中創建了admin用戶,且擁有“userAdminAnyDatabase”角色
下面講解基於角色的訪問控制
角色是授予User在指定資源上執行指定操作的權限,MongoDB官方手冊對角色的定義是:
A role grants privileges to perform the specified actions on resource.
MongoDB為了方便管理員管理權限,在DB級別上預先定義了內置角色;如果用戶需要對權限進行更為細致的管理,MongoDB允許用戶創建自定義的角色,能夠在集合級別上控制User能夠執行的操作。
MongoDB使用角色(Role)授予User訪問資源的權限,Role決定User能夠訪問的數據庫資源和執行的操作。一個User能夠被授予一個或多個Role,如果User沒有被授予Role,那么就沒有訪問MongoDB系統的權限。
A user is granted one or more roles that determine the user’s access to database resources and operations. Outside of role assignments, the user has no access to the system.
1,內置角色(Built-In Roles)
內置角色是MongoDB預定義的角色,操作的資源是在DB級別上。MongoDB擁有一個SuperUser的角色:root,擁有最大權限,能夠在系統的所有資源上執行任意操作。
數據庫用戶角色(Database User Roles):
- read:授予User只讀數據的權限
- readWrite:授予User讀寫數據的權限
數據庫管理角色(Database Administration Roles):
- dbAdmin:在當前dB中執行管理操作
- dbOwner:在當前DB中執行任意操作
- userAdmin:在當前DB中管理User
備份和還原角色(Backup and Restoration Roles):
- backup
- restore
跨庫角色(All-Database Roles):
- readAnyDatabase:授予在所有數據庫上讀取數據的權限
- readWriteAnyDatabase:授予在所有數據庫上讀寫數據的權限
- userAdminAnyDatabase:授予在所有數據庫上管理User的權限
- dbAdminAnyDatabase:授予管理所有數據庫的權限
現在我們舉例子介紹一下
上面我們已經創建好了admin用戶,該用戶擁有有grant權限,我們創建的admin用戶是在admin數據庫中創建的。即:賬號管理的授權權限。注意一點,帳號是跟着庫走的,所以在指定庫里授權,必須也在指定庫里驗證(auth)。
由於我們的admin用戶建立了 userAdminAnyDatabase 角色,用來管理用戶,可以通過這個角色來創建、刪除用戶。驗證:需要開啟auth參數
[root@:vg_adn_tidbCkhsTest:23.22.172.65:172.31.22.29 /usr/local/mongodb]#bin/mongo -u "admin" -p "123456" --authenticationDatabase "admin" MongoDB shell version v3.4.18 connecting to: mongodb://127.0.0.1:27017 MongoDB server version: 3.4.18 > db test > use admin switched to db admin > db admin > show users; { "_id" : "admin.admin", "user" : "admin", "db" : "admin", "roles" : [ { "role" : "dbOwner", "db" : "test" }, { "role" : "userAdminAnyDatabase", "db" : "admin" } ] } > show dbs; admin 0.000GB local 0.000GB test 0.000GB test1 0.000GB
我們連接上去admin用戶之后,在admin數據庫中就有了權限,注意admin用戶擁有的角色是userAdminAnyDatabase。所以才可以創建用戶等等操作
> use test2 #在test2庫中創建賬號 switched to db test2 > db.createUser( ... { ... user:"test", ... pwd:"test", ... roles:[{role:"readWrite",db:"test2"}] ... } ... ) Successfully added user: { "user" : "test", "roles" : [ { "role" : "readWrite", "db" : "test2" } ] } > show users; { "_id" : "test2.test", "user" : "test", "db" : "test2", "roles" : [ { "role" : "readWrite", "db" : "test2" } ] }
現在我們開始驗證一下:
> use test2 switched to db test2> db test2 > db.abc.insert({"name":"chaofeng","id":1}) WriteResult({ "writeError" : { "code" : 13, "errmsg" : "not authorized on test2 to execute command { insert: \"abc\", documents: [ { _id: ObjectId('5bea73410816d4c446c6c0d1'), name: \"chaofeng\", id: 1.0 } ], ordered: true }" } })
因為我目前還是admin登錄的,所以在test2數據庫中,admin用戶沒有權限,只有我們剛剛建立的“test”用戶才有權限。
注意:admin用戶只是擁有了創建用戶,刪除用戶的角色,這並不是最高權限。
所以現在我想在test2數據庫下插入數據,我得使用test用戶才行。
這里還要注意一點:
1、我在admin數據庫中認證test用戶
> db.auth("test","test") Error: Authentication failed. 0 > db admin
我在admin數據庫中使用test用戶認,來讓test用戶可以訪問test2數據庫,是失敗的。記住一點:在admin下創建的賬戶,不能直接在admin庫上驗證。
2、我在test2數據庫中認證test用戶
> db.auth("test","test") 1 > db test2
這樣就成功了,記住一點:在哪個庫上創建的賬戶,就在那里認證,也說明了一點,數據庫賬戶是跟着數據庫走的,先有數據庫,然后才有賬戶去認證這個數據庫,從而有權限操作。
現在我們的test用戶已經可以登錄到test2數據庫中操作了,我們嘗試一下
> use test2 switched to db test2> db.abc.insert({"name":"chaofeng","id":1}) WriteResult({ "nInserted" : 1 }) > db.abc.find() { "_id" : ObjectId("5bea76f00816d4c446c6c0d2"), "name" : "chaofeng", "id" : 1 } >
最后我們再看一下數據庫中創建的所有賬戶
> use admin switched to db admin> db.system.users.find().pretty() { "_id" : "admin.admin", "user" : "admin", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "2VmpmkRbVjolDoXjzbjHTw==", "storedKey" : "/Rd7OGTHEsGhsK8ZsFGe8DOzHTk=", "serverKey" : "8+JA2FBdUVtvo3AZNNDSvREZpOg=" } }, "roles" : [ { "role" : "dbOwner", "db" : "test" }, { "role" : "userAdminAnyDatabase", "db" : "admin" } ] } { "_id" : "test1.ccf", "user" : "ccf", "db" : "test1", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "cqPSk8h1ucAnJEl3mjx8MQ==", "storedKey" : "kNNTRqVv63fVy0r1KH9Oem0iKNo=", "serverKey" : "yTO6i7IIu7wuTEfd+VJG/l59veM=" } }, "roles" : [ { "role" : "readWrite", "db" : "test1" } ] } { "_id" : "test2.test", "user" : "test", "db" : "test2", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "0K+o35PrySZbdTq0kl79vg==", "storedKey" : "z3Z8dDswfQsnJ98qpUG8qChIafQ=", "serverKey" : "b6kLZoYhZwgxXmSNLpVIqyr6AyE=" } }, "roles" : [ { "role" : "readWrite", "db" : "test2" } ] }
查看所有的用戶我們必須在admin數據庫下,在其他的數據中是查看不到的。比如
> use test2 switched to db test2 > db.system.users.find().pretty()
同樣的查看數據庫用戶的指令,在test2數據庫中就不起作用,什么也查不出來。
同樣的道理,當我們登錄到mongo的時候,想要進入到admin庫中查看所有用戶的操作也是需要驗證的,比如:
[root@:vg_adn_tidbCkhsTest /usr/local/mongodb]#bin/mongo MongoDB shell version v3.4.18 connecting to: mongodb://127.0.0.1:27017 MongoDB server version: 3.4.18 > db test > use test2 switched to db test2 > use admin switched to db admin > db.system.users.find().pretty() Error: error: { "ok" : 0, "errmsg" : "not authorized on admin to execute command { find: \"system.users\", filter: {} }", "code" : 13, "codeName" : "Unauthorized" } >
緊接着這里我們還沒有在test2庫中認證賬戶密碼,還能訪問數據庫嗎?
> use test2 switched to db test2 > show dbs #發現連數據庫都查看不了 2018-11-13T07:09:19.437+0000 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:814:19 shellHelper@src/mongo/shell/utils.js:704:15 @(shellhelp2):1:1 > db.abc.find() #test2數據庫的記錄也查看不了 Error: error: { "ok" : 0, "errmsg" : "not authorized on test2 to execute command { find: \"abc\", filter: {} }", "code" : 13, "codeName" : "Unauthorized" } > db.auth("test","test"); #開啟認證賬戶 1 > db.abc.find() #成功 { "_id" : ObjectId("5bea76f00816d4c446c6c0d2"), "name" : "chaofeng", "id" : 1 } >
總結:mongo數據庫和別的數據庫認證過程是不一樣的,我們無需退出客戶端便可以自動切換用戶,來實現對不同數據庫的操作。mongo中,在哪個數據庫下創建的用戶,就在哪個數據庫下開啟認證,也就是說,在A數據庫創建的用戶user1,只能在數據庫A下面開啟認證,在B數據庫下面認證user1是不能成功的,在B數據庫下只能認證user2數據庫。數據庫賬戶是跟着數據庫走的。
現在我想刪除數據庫,
> use test2 switched to db test2 > show dbs admin 0.000GB local 0.000GB test1 0.000GB test2 0.000GB > db.auth("test","test"); 1 > db.abc.find() { "_id" : ObjectId("5bea76f00816d4c446c6c0d2"), "name" : "chaofeng", "id" : 1 } { "_id" : ObjectId("5bea7b4f6aeeebc0eb076f44"), "name" : "chen", "id" : 2 } > db.dropDatabase(); { "ok" : 0, "errmsg" : "not authorized on test2 to execute command { dropDatabase: 1.0 }", "code" : 13, "codeName" : "Unauthorized" }
發現是不能刪除數據庫的,仔細一想就知道test用戶只有對當前test2數據庫讀寫操作,但是沒有刪除權限。
我們再對test2數據庫創建一個用戶,使其擁有管理權限
> db test2 > db.createUser( ... { ... user:"gl", ... pwd:"gl", ... roles:[{role:"dbOwner",db:"test2"}] ... } ... ) Successfully added user: { "user" : "gl", "roles" : [ { "role" : "dbOwner", "db" : "test2" } ] }> db.auth("gl","gl") 1 > db.dropDatabase() { "dropped" : "test2", "ok" : 1 }
現在我們創建的gl用戶擁有dbOwner角色,也就是對當前數據庫擁有最高管理權限,這個時候就可以刪除數據庫test2了。