MongoDB认证与授权

敢说敢作敢为, 无怨无恨无悔。这篇文章主要讲述MongoDB认证与授权相关的知识,希望能为你提供帮助。
MongoDB认证与授权 目录[toc]
要想了解MongoDB的权限必须先了解如下一些关键字:

  • user:
    用户,用于提供客户端连接MongoDB的认证账户;
  • role:
    角色,数据权限的集合,创建用户的时候必须要指定对应的角色,否则用户无法操作数据库;
  • resource:
    资源,包括database或collection 也可以是database和collection的组合;
    {db:& lt; db& gt; , collection:& lt; collection& gt; }
  • actions:
    权限操作,定义了 user 能够对 resource document 执行的操作;
    如 增、删、改、查;
  • privilege:
    权限,privilege 是一组 resource 和 action的组合,对资源拥有什么操作称为权限;
  • authenticationDatabase:
    认证库,及创建角色或用户时所在的库;
    如,在admin下创建MongoDB用户那么登录的时候需要指定认证库 admin;
    在 test 库下创建的用户登录的时候指定认证库 test;
权限认证 MondoDB单实例认证
MongodDB存储所有的用户信息在admin数据库的集合system.users中,保存数据库、密码和数据库信息。MongoDB默认不启用权限认证,只要能连接到服务器,就可连接到mongod。
若要启用安全认证,需要更改配置文件Authorization,也可简写为 auth。或者在命令行启动MongoDB时加上 -auth参数启动,这样当MongoDB启动后就需要用户和密码进行认证了。
这是老版本MongoDB2.x中:
vim /etc/mongod.conf auth = true

MongoDB3.x中:
vim /etc/mongod.conf security: authorization:enabled

但是,不使用用户名和密码依然可以连接到数据库。但是将没有权限查看数据库。
连接到数据库后,可以使用db.auth命令认证用户:
mongo use admin db.auth("user","pwd")

或直接 mongo 127.0.0.1/admin -u user -p 来连接数据库。
MongoDB副本集认证
如果在副本集机制下开启了 -auth 认证,那么此时MongoDB副本集状态就会变成不健康状态,这就需要另外一个认证方式 KeyFile
简单来说 KeyFile 就是用在副本集群间开启认证的情况下需要的另一种认证方式,用来验证集群间身份的。
在各个节点的配置文件中加入KeyFile(600):
vim /etc/mongod.confsecurity: authorization:enabled KeyFile:/path/.KeyFile

角色管理MondoDB支持基于角色的访问控制(RBAC)来管理对MongoDB系统的访问。一个用户可以被授权一个或多个角色以决定该用户对数据库资源和操作的访问权限。在权限以外,用户是无法访问系统的。
数据库角色在创建用户的role参数中设置。角色分为內建角色和自定义角色。
內建角色
MongoDB內建角色包括以下几类:
数据库读写角色
read:允许用户读取指定数据库; readWrite:允许用户读写指定数据库;

数据库管理员角色 dbAdmin允许用户进行索引创建、删除,查看统计或访问system.profile,但没有角色和用户管理的权限;
userAdmin提供了在当前数据库中创建和修改角色和用户的能力;
包含如下action
  • changeCustomData
  • changePassword
  • createRole
  • createUser
  • dropRole
  • dropUser
  • grantRole
  • revokeRole
  • setAuthenticationRestriction
  • viewRole
  • viewUser
dbOwner提供对数据库执行任何操作的能力。这个角色组合了readWrite、dbAdmin和userAdmin角色授权的特权;
集群管理角色
hostManager:提供监视和管理服务器的能力; clusterManager:在集群上提供管理和监视操作。可以访问配置和本地数据库,这些数据库分别用于分片和复制; clusterMonitor:提供对监控工具的只读访问; clusterAdmin:提供最强大的集群管理访问(副本集、分片、主从等)。组合了clusterManager、clusterMonitor和hostManager角色的能力,还提供了dropDatabase操作;

备份恢复角色
backup:提供备份数据所需的能力; restore: 提供使用mongorestore恢复数据的能力;

所有数据库角色
readAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读权限; readWriteAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读写权限; userAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的userAdmin权限; dbAdminAnyDataBase:只在admin数据库中可用,赋予用户所有数据库的adAdmin权限;

超级用户角色
root:超级权限,只能针对admin库;

内部角色
__system:提供对数据库中任何对象的任何操作的特权;

自定义角色
MongoDB内置角色一般来说都是够用的,但当内置角色不满足需求时就可以自定义角色了。使用 db.createRole() 方法来自定义角色。
只能在 admin库 中创建角色;
use admin db.createRole( { role: "< name> ", privileges: [ { resource: { < resource> }, actions: [ "< action> ", ... ] }, ... ], roles: [ { role: "< role> ", db: "< database> " } | "< role> ", ... ], authenticationRestrictions: [ { clientSource: ["< IP> " | "< CIDR range> ", ...], serverAddress: ["< IP> " | "< CIDR range> ", ...] }, ... ] } )

权限由资源和action组合而成
resourcemongodb中resource分为如下几类
数据库或集合语法:
{ db: < database> , collection: < collection> }

指定数据库集合
{ db: "products", collection: "inventory" }

指定数据库
{ db: "products", collection: "" }

跨库指定集合
{ db: "", collection: "inventory" }

指定所有库所有集合
{ db: "", collection: "" }

集群资源
{ cluster : true }

任意资源
{ anyResource: true }

action 读写action
  • find
  • insert
  • remove
  • update
  • bypassDocumentValidation
  • useUUID
数据库管理action
  • changeCustomData
  • changeOwnCustomData
  • changeOwnPassword
  • changePassword
  • createCollection
  • createIndex
  • createRole
  • createUser
  • dropCollection
  • dropRole
  • dropUser
  • enableProfiler
  • grantRole
  • killCursors
  • killAnyCursor
  • revokeRole
  • setAuthenticationRestriction
  • unlock
  • viewRole
  • viewUser
操作角色 创建角色自定义一个角色,角色拥有任意数据库上的赋予、收回、查看角色的权限
use admin db.createRole( { role: "grantRevokeRoleAnyDB", privileges: [ { resource :{ db: "", collection: ""}, actions: ["grantRole", "revokeRole", "viewRole"] } ], roles: [] } )

查看角色
  • db.getRole()
admin@undefined$ db.getRoles() [ { "role" : "grantRevokeRoleAnyDB", "db" : "admin", "isBuiltin" : false, "roles" : [ ], "inheritedRoles" : [ ] } ]

  • db.system.roles.find()
admin@undefined$ db.system.roles.find().pretty() { "_id" : "admin.grantRevokeRoleAnyDB", "role" : "grantRevokeRoleAnyDB", "db" : "admin", "privileges" : [ { "resource" : { "db" : "", "collection" : "" }, "actions" : [ "grantRole", "revokeRole", "viewRole" ] } ], "roles" : [ ] }

角色继承
-- 语法 db.grantRolesToRole( "< rolename> ", [ < roles> ], { < writeConcern> } )

【MongoDB认证与授权】roles字段,可以指定内置角色,也可以是自定义角色
role有两种方式:
  • 只指定角色,比如read,那角色默认作用的数据库为运行如上命令所在的数据库
  • 指定db和角色
db.grantRolesToRole("grantRevokeRoleAnyDB",["read"]) db.grantRolesToRole("grantRevokeRoleAnyDB",[{role: "readWrite", db:"test"}])#这里的db不能指定为"" # 查看 db.getRoles() [ { "role" : "grantRevokeRoleAnyDB", "db" : "admin", "isBuiltin" : false, "roles" : [ { "role" : "read", "db" : "admin" }, { "role" : "readWrite", "db" : "test" } ], "inheritedRoles" : [ { "role" : "read", "db" : "admin" }, { "role" : "readWrite", "db" : "test" } ] } ] # 通过getRoles函数,看不到了role自定义的权限 # 使用db.system.roles.find() db.system.roles.find().pretty() { "_id" : "admin.grantRevokeRoleAnyDB", "role" : "grantRevokeRoleAnyDB", "db" : "admin", "privileges" : [ { "resource" : { "db" : "", "collection" : "" }, "actions" : [ "grantRole", "revokeRole", "viewRole" ] } ], "roles" : [ { "role" : "read", "db" : "admin" }, { "role" : "readWrite", "db" : "test" } ] }

角色回收db.revokeRolesfromRole()
与角色继承用法一样
db.revokeRolesFromRole("grantRevokeRoleAnyDB",["read"]) db.system.roles.find().pretty() { "_id" : "admin.grantRevokeRoleAnyDB", "role" : "grantRevokeRoleAnyDB", "db" : "admin", "privileges" : [ { "resource" : { "db" : "", "collection" : "" }, "actions" : [ "grantRole", "revokeRole", "viewRole" ] } ], "roles" : [ { "role" : "readWrite", "db" : "test" } ] }db.revokeRolesFromRole("grantRevokeRoleAnyDB",[{db: "test", role:"readWrite"}]) db.system.roles.find().pretty() { "_id" : "admin.grantRevokeRoleAnyDB", "role" : "grantRevokeRoleAnyDB", "db" : "admin", "privileges" : [ { "resource" : { "db" : "", "collection" : "" }, "actions" : [ "grantRole", "revokeRole", "viewRole" ] } ], "roles" : [ ] }

用户管理 创建用户
db.createUser({ user:"xxx", pwd:"xxxx", roles:[{#指定角色名称,以及作用于何数据库 role:"xxx", db:"xxxx" }] })

查看用户
  • db.getUsers()
?获取当前认证库下的所有用户
test@undefined$ db test test@undefined$ db.getUsers() [ { "_id" : "test.user1", "userId" : UUID("26cb7625-8f2f-421d-95e4-15e6150e969b"), "user" : "user1", "db" : "test", "roles" : [ { "role" : "read", "db" : "test" } ], "mechanisms" : [ "SCRAM-SHA-1", "SCRAM-SHA-256" ] } ] test@undefined$ use admin switched to db admin admin@undefined$ db.getUsers() [ { "_id" : "admin.root", "userId" : UUID("c80ec145-da32-4192-bd23-4639da5e6d91"), "user" : "root", "db" : "admin", "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ], "mechanisms" : [ "SCRAM-SHA-1", "SCRAM-SHA-256" ] } ]

  • db.getUser("user")
?获取当前认证库下指定用户
#再创建一个用户 test@undefined$ db.createUser({ ...user: "user2", ...pwd: "password2", ...roles: [ { role: "read", db: "test" } ] ... }) Successfully added user: { "user" : "user2", "roles" : [ { "role" : "read", "db" : "test" } ] } # test 库下有两个用户 test@undefined$ db.getUsers() [ { "_id" : "test.user1", "userId" : UUID("26cb7625-8f2f-421d-95e4-15e6150e969b"), "user" : "user1", "db" : "test", "roles" : [ { "role" : "read", "db" : "test" } ], "mechanisms" : [ "SCRAM-SHA-1", "SCRAM-SHA-256" ] }, { "_id" : "test.user2", "userId" : UUID("756272ed-a8ff-4333-bee2-7998454e4f15"), "user" : "user2", "db" : "test", "roles" : [ { "role" : "read", "db" : "test" } ], "mechanisms" : [ "SCRAM-SHA-1", "SCRAM-SHA-256" ] } ] # 获取指定用户 test@undefined$ db.getUser("user2") { "_id" : "test.user2", "userId" : UUID("756272ed-a8ff-4333-bee2-7998454e4f15"), "user" : "user2", "db" : "test", "roles" : [ { "role" : "read", "db" : "test" } ], "mechanisms" : [ "SCRAM-SHA-1", "SCRAM-SHA-256" ] }

  • db.system.users.find()
    获取所有用户信息
test@undefined$ use admin switched to db admin admin@undefined$ db.system.users.find().pretty() { "_id" : "admin.root", "userId" : UUID("c80ec145-da32-4192-bd23-4639da5e6d91"), "user" : "root", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "cdKArk1NhxpvFmvTvKCItA==", "storedKey" : "HUo9S9XjOB8m3d8ZXFFxPjqAK5Q=", "serverKey" : "rGnwDfRi/z2jfiGkwWWsUTPkGkQ=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "KagWAruayVEUbNf5l0dOenrXb05HqtRIXs6CkA==", "storedKey" : "5le156+HTjcN3VzXIaEypi3pZ7RSDy0fDpDRyW5B1N8=", "serverKey" : "iTjmBP/wP5drO2rE1IM+GvIEfuDDUM3IvGhjuydI7PI=" } }, "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ] } { "_id" : "test.user1", "userId" : UUID("26cb7625-8f2f-421d-95e4-15e6150e969b"), "user" : "user1", "db" : "test", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "iNKugTh/fVlal5d22vTQlQ==", "storedKey" : "D6TOl2P5v8wboGf12LHr3796J7I=", "serverKey" : "63e+PWI+F5arREp9SsEcHFrWHPY=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "g2rNWPU42wAkcWWrrdZFEM3jCug7puS1tn8CWg==", "storedKey" : "nPXRMJkRmMFP8ytWmACpYCmVnEHV+GIRHA6TKiZLmPY=", "serverKey" : "rxu1f4Bi8JJxFpWJZa8OwRog0eVzFHYraFAyMIf+iVE=" } }, "roles" : [ { "role" : "read", "db" : "test" } ] } { "_id" : "test.user2", "userId" : UUID("756272ed-a8ff-4333-bee2-7998454e4f15"), "user" : "user2", "db" : "test", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "DmLYgaL4oc8HE3qZghrjYQ==", "storedKey" : "uPUI6RayJpNasyRVvQSuCvoxYXc=", "serverKey" : "PbpZfK2UgCphoa8pkGCtGN69mjk=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "EyRe0aaqeUmOUZKSMu8kEqOqzqBKY4Enw7tnhg==", "storedKey" : "Rill2kRC3rELi0uu4M8Efjeny6KbDs2g8so+35cEk2M=", "serverKey" : "7yEHeydWZl5Hlnrj6ZnABEnD2JVB05W+2nUsal2P5aA=" } }, "roles" : [ { "role" : "read", "db" : "test" } ] }

用户角色管理
赋予角色创建用户时,可以不指定角色。
db.createUser( ...{ ...user: "user1", ...pwd: "password1", ...roles: [] ...} ... ) Successfully added user: { "user" : "user1", "roles" : [ ] }

创建完用户后,可以授予用户角色
db.grantRolesToUser( ..."user1", ...[{ role: "read", db: "test"}] ... )db.getUser("user1") { "_id" : "admin.user1", "userId" : UUID("62952ca2-5c70-464e-ba0a-6176101649f7"), "user" : "user1", "db" : "admin", "roles" : [ { "role" : "read", "db" : "test" } ], "mechanisms" : [ "SCRAM-SHA-1", "SCRAM-SHA-256" ] }

收回角色
db.revokeRolesFromUser( "user1", [{ role: "read", db: "test"}] )db.getUser("user1") { "_id" : "admin.user1", "userId" : UUID("62952ca2-5c70-464e-ba0a-6176101649f7"), "user" : "user1", "db" : "admin", "roles" : [ ], "mechanisms" : [ "SCRAM-SHA-1", "SCRAM-SHA-256" ] }

删除用户
db.dropUser("user1")# 删除当前库下user1用户 db.dropAllUsers()#删除当前库所有用户

修改密码
db.changeUserPassword("user","new_passwd")

更新用户
db.updateUser( username, update, writeConcern )
语法:
db.updateUser( "< username> ", { customData : { < any information> }, roles : [ { role: "< role> ", db: "< database> " } | "< role> ", ... ], pwd: passwordPrompt(),// Or"< cleartext password> " authenticationRestrictions: [ { clientSource: ["< IP> " | "< CIDR range> ", ...], serverAddress: ["< IP> ", | "< CIDR range> ", ...] }, ... ], mechanisms: [ "< SCRAM-SHA-1|SCRAM-SHA-256> ", ... ], passwordDigestor: "< server|client> " }, writeConcern: { < write concern> } )

指定的字段,将完全替换先前的字段值
示例:
在products库里创建appClient01用户
db.createUser( { user : "appClient01", pwd: passwordPrompt(), customData : { empID : "12345", badge : "9156" }, roles : [ { role : "readWrite", db: "products" }, { role : "read", db: "inventory" } ], mechanisms : [// Starting in MongoDB 4.0 "SCRAM-SHA-1", "SCRAM-SHA-256" ], authenticationRestrictions : [ { clientSource: ["69.89.31.226"], serverAddress: ["172.16.254.1"] } ] } )

完全替换customData和roles字段
use products db.updateUser( "appClient01", { customData : { employeeId : "0x3039" }, roles : [ { role : "read", db : "assets"} ] } ) # 查看替换结果 use admin db.system.users.find({user:"appClient01"}).pretty() { "_id" : "products.appClient01", "userId" : UUID("c4309b54-5fbd-49d2-aa79-223f441257e2"), "user" : "appClient01", "db" : "products", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "/vCAfg09papZ1vcYLEzw+w==", "storedKey" : "L0THU8ODHL8Sg4hv5FrVo3aphZU=", "serverKey" : "c2Q5UpaffvFD2ctwPfRon6OweaA=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "6GIelp+V63thV8Xp2LZRlVVPjG9601jFLlQz0w==", "storedKey" : "fCbnx0NF7BmkUvvJyYqK2dVxt7c32n4eYt96P7d9Xu8=", "serverKey" : "5sqiadkBHSDv42Wc99sH3u2+LpnBm6/Ge9oNt09JweA=" } }, "authenticationRestrictions" : [ { "clientSource" : [ "69.89.31.226" ], "serverAddress" : [ "172.16.254.1" ] } ], "customData" : { "employeeId" : "0x3039" }, "roles" : [ { "role" : "read", "db" : "assets" } ] }

可见只修改了customData和roles列

    推荐阅读