在文档中,system.users集合中的文件有如下模式:

{
  _id: <system defined id>,
  userId : <system assigned UUID>,  // Starting in MongoDB 4.0.9
  user: "<name>",
  db: "<database>",
  credentials: { <authentication credentials> },
  roles: [
           { role: "<role name>", db: "<database>" },
           ...
         ],
  customData: <custom information>,
  authenticationRestrictions : [ <documents> ] // Starting in MongoDB 4.0
 }

其中的db字段是用于authentication用的,也就是连接mongodb的时候,指定的--authenticationDatabase选项的值。
roles字段里面的db是指这个用户具体对db具有什么样的角色,是只读,只写,还是读写,也就是授权。这个db跟最外面的db没有任何关系,完全是用来指定权限的。
:认证的db字段不能在创建用户时指定,它的值是你创建用户时所在的那个db。

roles 详解:

read : 授权User只读数据的权限,允许用户读取指定的数据库
readWrite 授权User读/写数据的权限,允许用户读/写指定的数据库

dbAdmin:在当前的数据库中执行管理操作,如索引的创建、删除、统计、查看等
dbOwner:在当前的数据库中执行任意操作,增、删、改、查等
userAdmin :在当前的数据库中管理User,创建、删除和管理用户。

readAnyDatabase:授权在所有的数据库上读取数据的权限,只在admin 中可用
readWriteAnyDatabase:授权在所有的数据库上读写数据的权限,只在admin 中可用
userAdminAnyDatabase:授权在所有的数据库上管理User的权限,只在admin中可用
dbAdminAnyDatabase: 授权管理所有数据库的权限,只在admin 中可用

clusterAdmin:授权管理集群的最高权限,只在admin中可用
clusterManager:授权管理和监控集群的权限
clusterMonoitor:授权监控集群的权限,对监控工具具有readonly的权限
hostManager:管理server

root :超级账户和权限,只在admin中可用

连接Mongodb的时候,除了需要用户名,密码,还需要指定这个用户的认证db。为什么需要指定这个认证db?是因为Mongodb允许存在多个同名的用户存在,但同名的用户认证db必须不能相同。

对认证进行测试,在admin库和db1库下都创建一个user1用户,都给db1库授权dbOwner的权限,然后在db2库下创建user2用户,给db2库授权dbOwner的权限:

use admin
db.createUser({user:"user1",pwd:"123456",roles:[{role:"dbOwner",db:"db1"}]})
use db1
db.createUser({user:"user1",pwd:"123456",roles:[{role:"dbOwner",db:"db1"}]})
use db2
db.createUser({user:"user2",pwd:"123456",roles:[{role:"dbOwner",db:"db2"}]})

然后在admin库执行db.system.users.find().pretty()查看全局所有账户:

{
	"_id" : "admin.admin",
	"userId" : UUID("89216994-f357-4948-8231-6b7b95e1f7ec"),
	"user" : "admin",
	"db" : "admin",
	"credentials" : {
		"SCRAM-SHA-1" : {
			"iterationCount" : 10000,
			"salt" : "gQ4WsxURGIiwQUjiEwEXqQ==",
			"storedKey" : "Y9zxvDQIdb7Y+SNPu20HuBqKmoM=",
			"serverKey" : "F5S8dviRWZU/CxqCTl7YSwv4OzY="
		},
		"SCRAM-SHA-256" : {
			"iterationCount" : 15000,
			"salt" : "4t0gBMginSXCyVVMkk9hZjDvRIIheX2mqNEe6w==",
			"storedKey" : "RLupsaMljaBPchLPeGQGMOTbXh15ajYhKKi+Fl5dvNk=",
			"serverKey" : "XqluoV0mSWER7AOtR6AzvLCxGIUQl2fGMVfsf/zRTvY="
		}
	},
	"roles" : [
		{
			"role" : "root",
			"db" : "admin"
		}
	]
}
{
	"_id" : "db1.user1",
	"userId" : UUID("2b37999c-368d-4b7c-85a3-50ef07c75905"),
	"user" : "user1",
	"db" : "db1",
	"credentials" : {
		"SCRAM-SHA-1" : {
			"iterationCount" : 10000,
			"salt" : "0ZSvBZDzb5Teqp9qQrkcLg==",
			"storedKey" : "G1OKlMHgUnxX4wqWtl6KNBuemH4=",
			"serverKey" : "BI4NI2nc74oXpBDGrvWkk2HiASk="
		},
		"SCRAM-SHA-256" : {
			"iterationCount" : 15000,
			"salt" : "cxL4BzX4rMcap54LBPQrxfAjT7p2lTgWdVMeUQ==",
			"storedKey" : "xD/Dq4PqC50dPuxOAJT7PI+LoJVRFB7s+m435JaPtyk=",
			"serverKey" : "v4/HZj2x2mBNz60iwoiFKnqg2rqDBA4EOukx7sZjzcQ="
		}
	},
	"roles" : [
		{
			"role" : "dbOwner",
			"db" : "db1"
		}
	]
}
{
	"_id" : "admin.user1",
	"userId" : UUID("a5c845d0-7a12-4efe-9325-b387b6e0ca23"),
	"user" : "user1",
	"db" : "admin",
	"credentials" : {
		"SCRAM-SHA-1" : {
			"iterationCount" : 10000,
			"salt" : "znJyijuYi4TR05hbolm1sg==",
			"storedKey" : "9n09yF4FA126APfhy27dGUWP+5Q=",
			"serverKey" : "6dsRffqchtgUDZwEcj3iMIoeEHA="
		},
		"SCRAM-SHA-256" : {
			"iterationCount" : 15000,
			"salt" : "KncSKq/8TkmeR76o+vxL3qNKrULvLxAGeIL0wQ==",
			"storedKey" : "AyjgEWmAwwBbQ4pD8Yqo8YBkyXO+8zjqBIUeUEbzbF8=",
			"serverKey" : "OUbCWURxZMOaQPgoliZGqoTio076f+rDQKLPWCK8h7U="
		}
	},
	"roles" : [
		{
			"role" : "dbOwner",
			"db" : "db1"
		}
	]
}
{
	"_id" : "db2.user2",
	"userId" : UUID("da7f8aa8-1742-41f4-b5c5-7106f9dc0ea1"),
	"user" : "user2",
	"db" : "db2",
	"credentials" : {
		"SCRAM-SHA-1" : {
			"iterationCount" : 10000,
			"salt" : "mCobFqWHqUU1UpyLgKH0cg==",
			"storedKey" : "ROPf/ZuKjHZVXTTn4dzXdEOLCxk=",
			"serverKey" : "1jJ/cVKTmhwyXh+vAR9k0w+6zko="
		},
		"SCRAM-SHA-256" : {
			"iterationCount" : 15000,
			"salt" : "clrW58/Ep9Z8UqYb366jp+sJ9ld04xpqbSjmkA==",
			"storedKey" : "GwHz4zTIEkQL98kg5QhgeP0b+OBFV+nBH7GiCXIgFXs=",
			"serverKey" : "5gsCTZmw0pn4fTY2tU1QGJPE/GBIojWCjBzC0S9goMY="
		}
	},
	"roles" : [
		{
			"role" : "dbOwner",
			"db" : "db2"
		}
	]
}

发现user1用户在db1和admin库都有authentication,user2用户只有db2库有authentication。

接下来使用user1用户,authenticationDatabase选择admin库进行登录db1库测试:

root@mongo:/# mongo -u user1 -p 123456 --authenticationDatabase admin db1
MongoDB shell version v4.4.16
connecting to: mongodb://127.0.0.1:27017/db1?authSource=admin&compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("17a88d66-7f8b-4935-a608-34a7749d46ec") }
MongoDB server version: 4.4.16
> db.getName()
db1
> exit
bye

结果可以正常登入。

使用user1用户,authenticationDatabase选择db1库进行登录db1库测试:

root@mongo:/# mongo -u user1 -p 123456 --authenticationDatabase db1 db1
MongoDB shell version v4.4.16
connecting to: mongodb://127.0.0.1:27017/db1?authSource=db1&compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("8ea3ef78-1063-48f1-b57e-afef1f097439") }
MongoDB server version: 4.4.16
> db.getName()
db1
> exit
bye

结果也可以正常登入。

使用user2用户,authenticationDatabase选择db2库进行登录db2库测试:

root@mongo:/# mongo -u user2 -p 123456 --authenticationDatabase db2 db2
MongoDB shell version v4.4.16
connecting to: mongodb://127.0.0.1:27017/db2?authSource=db2&compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("0524fc0b-c364-47f9-b801-dd541e00047f") }
MongoDB server version: 4.4.16
> db.getName()
db2
> exit
bye

结果也可以正常登入。

使用user2用户,authenticationDatabase选择admin库进行登录db2库测试:

root@mongo:/# mongo -u user2 -p 123456 --authenticationDatabase admin db2
MongoDB shell version v4.4.16
connecting to: mongodb://127.0.0.1:27017/db2?authSource=admin&compressors=disabled&gssapiServiceName=mongodb
Error: Authentication failed. :
connect@src/mongo/shell/mongo.js:374:17
@(connect):2:6
exception: connect failed
exiting with code 1

发现不能登入。
如刚刚执行db.system.users.find().pretty()查看全局所有账户所示,user2用户没在admin库有authentication。

所以认证的db字段不能在创建用户时指定,它的值是你创建用户时所在的那个db。

use db2
db.createUser({user:“user2”,pwd:“123456”,roles:[{role:“dbOwner”,db:“db2”}]})

在这个user2用户里,认证的库是在db2中。