本文共 2308 字,大约阅读时间需要 7 分钟。
上篇文章说到,MongoDB的网络通讯协议流程。拿到请求对象后,会调用assemblyResonse函数处理。这部分的代码实在没什么章法可言,if-else
遍地,实在不怎么优雅。可以感受到随着需求的增长,很多代码都是硬套上去的。本篇介绍的是基本的处理请求,基本请求所指的是command命令以外的处理行为。
首先,获取到线程绑定(ThreadLocal)Client对象,并对权限模块初始化,更新Auth Cache中过期或者失效的权限信息。然后,根据配置记录diaglog;接着统计操作计数器。接着,调用receivedXXXX函数,执行相关请求,其间会对权限进行判断。最后,根据slowlog配置,记录Profiling数据。
Query为例:
try { ... Status status = client->getAuthorizationSession()->checkAuthForQuery(ns, q.query); audit::logQueryAuthzCheck(client, ns, q.query, status.code()); uassertStatusOK(status); ...catch (AssertionException& e) { ... ok = false;}
checkAuthForQuery之后会调用isAuthorizedForActionsOnNamespace做具体的验证功能:
if (!isAuthorizedForActionsOnNamespace(ns, ActionType::find)) { return Status(ErrorCodes::Unauthorized, str::stream() << "not authorized for query on " << ns.ns());}
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:
主要对Action和Resource封装,然后调用_isAuthorizedForPrivilege完成功能。
简单介绍下Privilege,Action就是对数据的操作,比如Query,Insert都可以归纳为Action;Resource就是数据集合,可以是Collection,也可以是DB,那Privilege就是Action*Privilege的组合,一个Privilege可以含有多个Action,但在Privilege维度上,Action都只能与一个(或者表达式)Resource组合。Privilege的集合可以组合成Role概念,方便用户配置。
这个函数的处理算法是,遍历授权过的所有用户,和待验证的Resource比较,如果找到,则对比Action,所有的Action都找到的话,则通过验证。
for (UserSet::iterator it = _authenticatedUsers.begin(); it != _authenticatedUsers.end(); ++it) { User* user = *it; for (int i = 0; i getActionsForResource(resourceSearchList[i]); unmetRequirements.removeAllActionsFromSet(userActions); if (unmetRequirements.empty()) return true; }}
转载地址:http://koooa.baihongyu.com/