onethink权限管理主要分为两个方面一种菜单节点检测,另一种是动态检测(未实现)。
第一次进入系统后,在Admin/Controller/AdminController.class.php中权限验证的代码为:
define('IS_ROOT', is_administrator());
if(!IS_ROOT && C('ADMIN_ALLOW_IP')){
// 检查IP地址访问
if(!in_array(get_client_ip(),explode(',',C('ADMIN_ALLOW_IP')))){
$this->error('403:禁止访问');
}
}
$access = $this->accessControl();
if ( $access === false ) {
$this->error('403:禁止访问');
}elseif( $access === null ){
$dynamic = $this->checkDynamic();//动态检测的代码,返回null
if( $dynamic === null ){
//检测非动态权限
$rule = strtolower(MODULE_NAME.'/'.CONTROLLER_NAME.'/'.ACTION_NAME);
if(!IS_ROOT) {
if (!$this->checkRule($rule, array('in', '1,2'))) {
$this->error('未授权访问!');
exit;
}
}
}elseif( $dynamic === false ){
$this->error('未授权访问!');
}
}
在onethink的数据库中有四张表是和权限管理有关联的,
其中rule表对应的是此系统中所有的url生成的规则表,group表对应的是某个分组所拥有的权限,也就是某个分组可以访问的url集合。group_access代表的某个用户属于某个组,extend表主要用来实现动态检测。
在/Admin/Controller/AdminController.class.php中进行的第一次权限检测,
/**
* action访问控制,在 **登陆成功** 后执行的第一项权限检测任务
*
* @return boolean|null 返回值必须使用 `===` 进行判断
*
* 返回 **false**, 不允许任何人访问(超管除外)
* 返回 **true**, 允许任何管理员访问,无需执行节点权限检测
* 返回 **null**, 需要继续执行节点权限检测决定是否允许访问
*
*/
final protected function accessControl(){
$allow = C('ALLOW_VISIT');
$deny = C('DENY_VISIT');#这两项配置存储在config表中
$check = strtolower(CONTROLLER_NAME.'/'.ACTION_NAME);
if ( !empty($deny) && in_array_case($check,$deny) ) {
return false;//非超管禁止访问deny中的方法
}
if ( !empty($allow) && in_array_case($check,$allow) ) {
return true;
}
return null;//需要检测节点权限
}
权限认证的配置在/ThinkPHP/Library/Think/Auth.class.php中如图:
规则验证中最重要的函数为check()函数:
public function check($name, $uid, $type=1, $mode='url', $relation='or') {
if (!$this->_config['AUTH_ON'])#如果没有开启验证,返回true
return true;
$authList = $this->getAuthList($uid,$type); //获取用户拥有的权限列表
if (is_string($name)) {
$name = strtolower($name);
if (strpos($name, ',') !== false) { #如果是多个,将其拆分成数组
$name = explode(',', $name);
} else {
$name = array($name);
}
}
$list = array(); //保存验证通过的规则名
if ($mode=='url') {
$REQUEST = unserialize( strtolower(serialize($_REQUEST)) );
}
foreach (