当前位置: 首页 > 后端技术 > PHP

yii对rbac的实现详解

时间:2023-03-30 06:10:00 PHP

之前有朋友问我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";}}}}?>">href="">">">admin->can($menu['module'].'/*')&&!Yii::$app->admin->can($menu['module'].'/'.$sub['url']))继续;?>

  • ">
  • 这样,实现不同登录用户显示不同菜单RBAC~~创建不同角色的原理:不同角色有不同的权限User->/*角色添加*/publicfunctionactionCreaterole(){if(Yii::$app->request->isPost){//DBmanager对象$auth=Yii::$app->authManager;//创建角色对象$role=$auth->createRole(null);$post=Yii::$app->request->post();if(empty($post['name'])||empty($post['description'])){thrownew\Exception('参数错误');}$role->name=$post['name'];$role->description=$post['description'];$role->ruleName=empty($post['rule_name'])?null:$post['rule_name'];$role->data=empty($p主机['数据'])?空:$post['数据'];if($auth->add($role)){Yii::$app->session->setFlash('info','添加成功');}}返回$this->render('_createitem');}原理:所谓分配权限就是给用户分配访问controller的权限,确认要分配的对象确实对应指定表的user_id和item_name值呢??看这里->/*分配权限*/publicfunctionactionAssignitem($name){//获取角色$name=htmlspecialchars($name);$auth=Yii::$app->authManager;//获取当前角色$parent=$auth->getRole($name);如果(Yii::$app->request->isPost){$post=Yii::$app->request->post();if(Rbac::addChild($post['children'],$name)){Yii::$app->session->setFlash('info','分配成功');}}$children=Rbac::getChildrenByName($名字);//获取当前用户的$roles=Rbac::getOptions($auth->getRoles(),$parent);//获取当前用户的权限$permissions=Rbac::getOptions($auth->getPermissions(),$parent);返回$this->render('_assignitem',['parent'=>$name,'roles'=>$roles,'permissions'=>$permissions,'children'=>$children]);}RBAC~~规则规范,更高级的权限规范接下来,不得不说说rbac规则,这是什么??所谓规则,其实就是对用户权限进行附加限制的原理:通过定义规则类,在添加用户时指定规则名称,可以实现对用户权限的附加限制。数据表中,数据字段是实例化的自定义规则Class对象比如我们定义这样一个自定义规则类/*实现分类只能被adder删除*/classAuthorRuleextendsRule{public$name="isAuthor";//当前用户、权限、附加参数publicfunctionexecute($user,$item,$params){$action=Yii::$app->controller->action->id;//删除方法的额外限制if($action=='delete'){//获取该用户添加的当前类别,不允许其他用户删除$cateid=Yii::$app->request->得到(“身份证”);$cate=类别::findOne($cateid);返回$cate->adminid==$user;}返回真;}}我们如何将这个规则创建到数据表中??/*创建规则*/publicfunctionactionCreaterule(){if(Yii::$app->request->is发布){$post=Yii::$app->request->post();if(empty($post['class_name'])){thrownew\Exception('参数错误');}//指定当前的$className="app\\models\\"。$post['class_name'];if(!class_exists($className)){thrownew\Exception('规则类不存在');}$rule=new$className;//使用authManager组件将当前规则类保存到数据库中if(Yii::$app->authManager->add($rule)){Yii::$app->session->setFlash('info','添加成功');}}返回$this->render("_createrule");这样在添加用户的时候就可以指定规则,进而实现更高级的指定权限。到这里,基本完成了用户创建、权限分配、规则规范,希望对大家有所帮助~~