对于各种数据库软件,启用认证的方法都不同,比如PG是在pg_hba.conf中对用户设置使用启用密码认证,而Oracle远程登录均需要使用密码认证。Mongodb是在参数中控制是否启用密码认证,并且启用后,对所有用户生效,并不能像PG一样对用户区别对待。需要启用认证,使用mongod --auth或者在参数文件中加入authorization: enabled。mongodb的认证分为用户验证(client auth)和集群间认证(internal auth),在复制集中启用认证需指定keyFile参数,指定后即默认启用了用户验证。
从3.0开始,mongodb默认采用SCRAM加密算法,在3.0以前默认使用MongoDB-CR算法,所以如果数据库是从2.X版本升级上来的数据库,可能出现认证机制不兼容导致客户端无法连接数据库的情况。另外mongodb还支持x.509算法,主要用于加密连接中,本人也未使用过,此处不做探讨。
一. 用户创建及管理
在Mongodb中的用户是基于数据库的,不同数据库中可以存在同名用户,所以在登录数据库的时候,需要指定mongo --authenticationDatabase=XX 参数选择认证数据库。在生产中,为了规范和便于管理,我们建议将所有用户都创建在admin库中。需要注意的是Mongodb默认是没有创建任何内置用户的,所以在数据库实例启用认证前,需要先创建一个超管账号,然后再重启实例启用认证。
——用户创建
<code>use admin db.createUser({user:"fhtest", pwd:"Ba@31^T2cy",roles:[{role:"read",db:"production"}]});</code>{role:"read",db:"production"},
表示在production库有read角色,可以看到roles值是一个数组,所以可以具有多个库的多种角色或者一个库的多种角色
——用户授权
——权限回收
——用户查询
二. 角色管理
从上面用户管理的命令可以看到,不管是授权还是回收权限,都是基于角色的,Mongodb不能直接将某个集合或者数据库的操作权限授予用户,只能通过role来进行授权,role可以是系统内置的,也可以是用户自定义的。
内置角色包括root、dbOwner、clusterAdmin、read、readWrite等,root角色相当于PG的superuser超管权限。在生产环境中,会有给用户授予所有数据库读权限的需求,类似oracle的select any table ,Mongodb中具有all database role,如readAnyDatabase、readWriteAnyDatabase等 ,详细内置role可查看官方文档。
由于不能将对象权限授予用户,所以当要进行精细的权限控制,内置角色无法满足需求,就只能自定义角色。自定义角色里面可以直接对对象(resource)进行操作(action)的权限,也可以包含某个角色。如:
<code>use admin db.createRole( { role: "myClusterwideAdmin", privileges: [ { resource: { cluster: true }, actions: [ "addShard" ] }, { resource: { db: "config", collection: "" }, actions: [ "find", "update", "insert", "remove" ] }, { resource: { db: "users", collection: "usersCollection" }, actions: [ "update", "insert", "remove" ] }, { resource: { db: "", collection: "" }, actions: [ "find" ] } ], roles: [ { role: "read", db: "admin" } ] }, { w: "majority" , wtimeout: 5000 } )</code>从上面的例子可以看出resource是一个子文档,包含db和collection,如果为空则表示所有对象,action是一个数组,包含需要授予的操作权限。
当然也可以将role授权给role,使用db.grantRolesToRole() 。
在生产环境中若,经常需要在mongo上执行javascript脚本,并且使用db.eval()调用javascript脚本,则可能出现如下报错,提示无权限

eval需要所有资源的所有权限,需创建如下角色并授予用户
<code>db.createRole( { role: "eval_role", privileges: [ { resource: { anyResource: true }, actions: [ "anyAction" ] } ], roles:[] } )</code>
在此,强烈不建议授予此类权限!调用javascript可以使用其他方案,比如load 。