大家都知道Yii可以通过CDbAuthManager进行简单的权限管理,在component下配置
'components' => array( 'authManager'=>array( 'class'=>'CDbAuthManager', 'connectionID'=>'db', ), )
就可以直接使用。数据库对应的AuthItemChild,`AuthItem,AuthAssignment三张表。
其中AuthItem是有哪些权限,AuthAssignment是给哪些用户分配权限,而AuthItemChild使用中一般为空。
后来经过慢SQL查询,发现总是有SELECT `parent`\nFROM `AuthItemChild`\nWHERE child=:name这样的情况,因为AuthItemChild为空,所以造成速度很慢。
在CDbAuthManager中发现有递归权限验证
protected function checkAccessRecursive($itemName,$userId,$params,$assignments) { if(($item=$this->getAuthItem($itemName))===null) return false; Yii::trace('Checking permission "'.$item->getName().'"','system.web.auth.CDbAuthManager'); if(!isset($params['userId'])) $params['userId'] = $userId; if($this->executeBizRule($item->getBizRule(),$params,$item->getData())) { if(in_array($itemName,$this->defaultRoles)) return true; if(isset($assignments[$itemName])) { $assignment=$assignments[$itemName]; if($this->executeBizRule($assignment->getBizRule(),$params,$assignment->getData())) return true; } $parents=$this->db->createCommand() ->select('parent') ->from($this->itemChildTable) ->where('child=:name', array(':name'=>$itemName)) ->queryColumn(); foreach($parents as $parent) { if($this->checkAccessRecursive($parent,$userId,$params,$assignments)) return true; } } return false; }
意思如果没有这个name的权限,就去AuthItemChild找parent,如果parent有权限,
那么自己也有权限。如果不使用,可以注释掉
// $parents=$this->db->createCommand() // ->select('parent') // ->from($this->itemChildTable) // ->where('child=:name', array(':name'=>$itemName)) // ->queryColumn(); // foreach($parents as $parent) // { // if($this->checkAccessRecursive($parent,$userId,$params,$assignments)) // return true; // }
最后可以用redis代替db来进行权限的管理,具体方法见http://www.yuansir-web.com/2013/07/30/%E5%88%A9%E7%94%A8redis-%E5%8A%A0%E9%80%9F-yii-cdbauthmanager/