之前有朋友问我yii的rbac是怎么做的。大学的时候接触过,但是用了很久没用,忘记了。思路,希望能帮到大家哈~~RBAC~~什么是RBAC基于角色的访问控制(Role-BasedAccessControl)作为一种传统的访问控制(自愿访问、强制访问)有替代前景,受到了广泛关注。在RBAC中,权限与角色相关联,用户通过成为相应角色的成员来获得这些角色的权限。这大大简化了权限的管理。在组织中,创建角色来完成各种任务,并根据用户的职责和资格为用户分配相应的角色。可以轻松地将用户从一个角色分配到另一个角色。可以根据新的需求和系统集成赋予角色新的权限,也可以根据需要收回角色的权限。可以建立角色与角色之间的关系,以涵盖更广泛的客观情况。RBAC~~权限认证流程用户登录后,对用户的角色进行认证。根据角色,查询该角色拥有的权限操作列表。当访问某个权限(操作)时,判断用户是否具有访问权限。yii如何实现??这里我们使用数据库的方式来实现,会比较安全的RBAC~~权限数据生成首先在web/console.php中配置组件'authManager'=>['class'=>'yii\rbac\DbManager',//auth_item(角色权限)//auth_item_child(角色->权限)//auth_assignment(用户->角色)//auth_rule(规则)'itemTable'=>'{{%auth_item}}','itemChildTable'=>'{{%auth_item_child}}','assignmentTable'=>'{{%auth_assignment}}','ruleTable'=>'{{%auth_rule}}',],然后使用yii脚本生成数据表。/yiimigrate--migrationPath=@yii/rbac/migrations/那么我们需要读取所有的controller和methods并存入permission表中,这样我们在判断的时候就可以读取数据库再进行判断。publicfunctionactionInit(){$trans=Yii::$app->db->beginTransaction();try{//构建控制器目录$dir=dirname(dirname(__FILE__)).'/模块/控制器';//查找控制器目录下的所有文件$controllers=glob($dir.'/*');$permissions=[];foreach($controllersas$controller){$content=file_get_contents($controller);//找到控制器preg_match('/class([a-zA-Z]+)Controller/',$content,$match);$cName=$match[1];$权限[]=strtolower($cName.'/*');//正则匹配文本soactionpreg_match_all('/publicfunctionaction([a-zA-Z_]+)/',$content,$matches);foreach($matches[1]as$aName){$permissions[]=strtolower($cName.'/'.$aName);$auth=Yii::$app->authManager;//为什么$auth可以对表进行操作foreach($permissionsas$permission){//权限是否存在if(!$auth->getPermission($permission)){$obj=$auth->createPermission($permission);$obj->description=$permission;$auth->add($obj);}}$trans->commit();echo"导入成功\n";}catch(\Exception$e){$trans->rollback();echo"导入失败\n";}}接下来yii下就可以生成权限数据了./yiirbac/init然后再看数据库RBAC的使用原理~~权限访问控制过滤器:权限的控制其实就是判断当前用户是否拥有访问方法和控制器的权利。在此之前,需要使用过滤器对用户的登录和非登录进行鉴权和过滤。所有控制器都扩展了CommonController。访问子类控制器时,会自动访问behaviors方法,在子控制器中,通过重写父类的属性来指定允许访问的方法,进而达到过滤的作用//子类可以通过重写这个属性来实现认证public$mustlogin=['createrule','createrole','roles','assignitem'];//行为过滤器publicfunctionbehaviors(){return['access'=>['class'=>\yii\filters\AccessControl::className(),'user'=>'admin','only'=>$this->actions,'except'=>$this->except,'rules'=>[['allow'=>false,'actions'=>empty($this->mustlogin)?[]:$this->mustlogin,'roles'=>['?'],],['allow'=>true,'actions'=>empty($this->mustlogin)?[]:$this->mustlogin,'roles'=>['@'],],],],];}//那么如何实现access判断用户是否有权限呢??Yii提供了beforeAction,在CommonContRollerjudges/*权限访问判断*/publicfunctionbeforeAction($action){//调用父类方法防止被覆盖if(!parent::beforeAction($action)){returnfalse;}//获取当前控制器$controller=$action->controller->id;$actionName=$action->id;如果(Yii::$app->admin->can($controller.'/*')){返回真;}if(Yii::$app->admin->can($controller.'/'.$actionName)){返回真;}thrownew\yii\web\UnauthorizedHttpException('抱歉,您没有权限'.$controller.'/'.$actionName.'Permission');//返回真;}//这样就可以实现权限的访问控制了。到这里,我们就实现了权限的访问判断,接下来我们要实现的是如何针对不同的用户显示不同的菜单呢??原理:将菜单栏以数组的形式存储,通过数组循环判断当前用户访问的controller是否有对应的权限controller->id;$action=Yii::$app->controller->action->id;//循环菜单foreach(Yii::$app->params['adminmenu']as$menu){$show="隐藏";如果(Yii::$app->admin->can($menu['module'].'/*')){$show="show";}else{if(empty($menu['submenu'])&&!Yii::$app->admin->can($menu['url'])){继续;}else{foreach($menu['submenu']as$sub){//判断当前用户是否可以访问控制器if(Yii::$app->admin->can($menu['module'].'/'.$sub['url'])){$show="show";}}}}?>
