上篇文章说到,mongodb的网络通讯协议流程。拿到请求对象后,会调用assemblyresonse函数处理。这部分的代码实在没什么章法可言,<code>if-else</code>遍地,实在不怎么优雅。可以感受到随着需求的增长,很多代码都是硬套上去的。本篇介绍的是基本的处理请求,基本请求所指的是command命令以外的处理行为。
首先,获取到线程绑定(threadlocal)client对象,并对权限模块初始化,更新auth cache中过期或者失效的权限信息。然后,根据配置记录diaglog;接着统计操作计数器。接着,调用receivedxxxx函数,执行相关请求,其间会对权限进行判断。最后,根据slowlog配置,记录profiling数据。
query为例:
checkauthforquery之后会调用isauthorizedforactionsonnamespace做具体的验证功能:
isauthorizedforactionsonnamespace函数用来验证资源和动作的权限合法性,不同的操作都对应自己的一套动作,相关的对应关系总结如下:
op_code
value
receivedxxxx
checkauthforxxxx
actiontype
op_update
2001
receivedupdate
checkauthforupdate
update
op_insert
2002
receivedinsert
checkauthforinsert
createindex/insert
op_query
2004
receivedquery
checkauthforquery
find
op_get_more
2005
receivedgetmore
checkauthforgetmore
listcollections/listindexes/find
op_delete
2006
receiveddelete
checkauthfordelete
remove
op_kill_cursors
2007
receivedkillcursors
checkauthforkillcursors
killcursors
ps:
2003操作代码已经废弃,目前是保留字段
command请求也是通过op_query发送过来的,对于command请求,代码上分之处理,个人不是很喜欢这个混用op_code的风格,也许是伟大的历史原因造成的
inprog killop unlock 不走以上流程,通过query包封装传递过来后,调用了相应的处理函数处理
command的权限验证额外说明
所有的actiontype定义在db/auth/action_types.txt中,非常多
主要对action和resource封装,然后调用_isauthorizedforprivilege完成功能。
简单介绍下privilege,action就是对数据的操作,比如query,insert都可以归纳为action;resource就是数据集合,可以是collection,也可以是db,那privilege就是action*privilege的组合,一个privilege可以含有多个action,但在privilege维度上,action都只能与一个(或者表达式)resource组合。privilege的集合可以组合成role概念,方便用户配置。
这个函数的处理算法是,遍历授权过的所有用户,和待验证的resource比较,如果找到,则对比action,所有的action都找到的话,则通过验证。