之前有个朋友问我yii的rbac怎么做,以前大学的时候有接触过,很长时间没用了,也忘记了,正好这几天比较闲,重新捋了下大体思路,希望可以帮到困在yii的rbac上的门外han~~
RBAC~~什么是RBAC
基于角色的权限访问控制(Role-Based Access
Control)作为传统访问控制(自主访问,强制访问)的有前景的代替受到广泛的关注。在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。在一个组织中,角色是为了完成各种工作而创造,用户则依据它的责任和资格来被指派相应的角色,用户可以很容易地从一个角色被指派到另一个角色。角色可依新的需求和系统的合并而赋予新的权限,而权限也可根据需要而从某角色中回收。角色与角色的关系可以建立起来以囊括更广泛的客观情况。
RBAC~~权限认证流程
用户登录后认证用户的角色
根据角色 查询出该角色拥有的权限操作列表
访问某一个权限(操作)时判断该用户是否拥有访问的能力
yii如何实现呢??这里我们采用数据库的方式实现,会相对来说比较安全
RBAC~~权限数据生成
首先在web/console.php中配置组件
'authManager' => [
'class' => 'yii\rbac\DbManager',
// auth_item (role permission)
// auth_item_child (role->permission)
// auth_assignment (user->role)
// auth_rule (rule)
'itemTable' => '{{%auth_item}}',
'itemChildTable' => '{{%auth_item_child}}',
'assignmentTable' => '{{%auth_assignment}}',
'ruleTable' => '{{%auth_rule}}',
],
接着使用yii脚本,生成数据表
./yii migrate --migrationPath=@yii/rbac/migrations/
然后我们需要读取所有的控制器与方法 存储到权限表,方便判断的时候 读取数据库 进而进行判断
public function actionInit()
{
$trans = Yii::$app->db->beginTransaction();
try {
//构建控制器目录
$dir = dirname(dirname(__FILE__)). '/modules/controllers';
//找到控制器目录下的所有文件
$controllers = glob($dir. '/*');
$permissions = [];
foreach ($controllers as $controller) {
$content = file_get_contents($controller);
//找到Controller即可
preg_match('/class ([a-zA-Z]+)Controller/', $content, $match);
$cName = $match[1];
$permissions[] = strtolower($cName. '/*');
//正则匹配文本中的所以action
preg_match_all('/public function action([a-zA-Z_]+)/', $content, $matches);
foreach ($matches[1] as $aName) {
$permissions[] = strtolower($cName. '/'. $aName);
}
}
$auth = Yii::$app->authManager;
//为什么$auth可以操作到该表
foreach ($permissions as $permission) {
//是否存在该权限
if (!$auth->getPermission($permission)) {
$obj = $auth->createPermission($permission);
$obj->description = $permission;
$auth->add($obj);
}
}
$trans->commit();
echo "import success \n";
} catch(\Exception $e) {
$trans->rollback();
echo "import failed \n";
}
}
接着yii下 就可以生成权限数据了
./yii rbac/init
然后,看看数据库
RBAC~~权限访问控制
过滤器的使用原理:
权限的控制实则就是判断当前的用户是否拥有对方法,控制器访问的权限 在这之前需要使用过滤器 对用户的登录与未登录进行认证过滤 ,所有的控制器 extends CommonController,在访问子类控制器的时候,会自动去访问behaviors方法,在子控制器中,通过重写父类的属性指定允许访问的方法,进而实现过滤的作用。
//子类可以通过重写该属性 实现认证
public $mustlogin = ['createrule', 'createrole', 'roles', 'assignitem'];
//行为过滤器
public function behaviors()
{
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' => ['@'],
],
],
],
];
}
//那么如何实现访问 判断用户是否拥有权限呢??yii提供了beforeAction,在CommonController进行判断
/*权限访问判断*/
public function beforeAction($action)
{
//调用父类方法 防止被重写掉
if (!parent::beforeAction($action)) {
return false;
}
//获取到当前的控制器
$controller = $action->controller->id;
$actionName = $action->id;
if (Yii::$app->admin->can($controller. '/*')) {
return true;
}
if (Yii::$app->admin->can($controller. '/'. $actionName)) {
return true;
}
throw new \yii\web\UnauthorizedHttpException('对不起,您没有访问'. $controller. '/'. $actionName. '的权限');
// return true;
}
//这样即可实现权限的访问控制
到这里,我们就是实现了权限的访问判断,接下来 我们还要实现 不同用户显示不同的菜单,如何实现呢??
原理:
将菜单栏以数组的形式进行存储,通过循环数组,判断当前用户访问的控制器是否拥有对应的权限
<?php
$controller = Yii::$app->controller->id;
$action = Yii::$app->controller->action->id;
//循环菜单
foreach (Yii::$app->params['adminmenu'] as $menu) {
$show = "hidden";
if (Yii::$app->admin->can($menu['module']. '/*')) {
$show = "show";
} else {
if (empty($menu['submenu']) && !Yii::$app->admin->can($menu['url'])) {
continue;
} else {
foreach ($menu['submenu'] as $sub) {
//判断当前的用户是否拥有访问该控制器的权限
if (Yii::$app->admin->can($menu['module']. '/'. $sub['url'])) {
$show = "show";
}
}
}
}
?>
<li class="<?php echo $controller == $menu['module'] ? 'active' : ''; echo $show; ?>">
<a <?php echo !empty($menu['submenu']) ? 'class="dropdown-toggle"' : ''; ?> href="<?php echo $menu['url'] == '#' ? '#' : yii\helpers\Url::to([$menu['url']]); ?>">
<i class="<?php echo $menu['icon'] ?>"></i>
<span><?php echo $menu['label']; ?></span>
<?php if (!empty($menu['submenu'])) : ?>
<i class="icon-chevron-down"></i>
<?php endif; ?>
</a>
<ul class="submenu <?php echo $controller == $menu['module'] && !empty($menu['submenu']) ? 'active' : ''; ?>">
<?php foreach ($menu['submenu'] as $sub): ?>
<?php if (!Yii::$app->admin->can($menu['module']. '/*') && !Yii::$app->admin->can($menu['module']. '/'. $sub['url'])) continue; ?>
<li><a href="<?php echo yii\helpers\Url::to([$menu['module']. '/'. $sub['url']]); ?>"><?php echo $sub['label'] ?></a></li>
<?php endforeach; ?>
</ul>
</li>
<?php
}
?>
这样就实现了不同登录用户 不同菜单的展示
RBAC~~创建不同角色
原理:
不同角色拥有不同权限,超级管理员可以创建用户,及分配权限给不同用户,首先我们得有个用户->
/*角色添加*/
public function actionCreaterole()
{
if (Yii::$app->request->isPost) {
//DBmanager对象
$auth = Yii::$app->authManager;
//创建一个role的对象
$role = $auth->createRole(null);
$post = Yii::$app->request->post();
if (empty($post['name']) || empty($post['description'])) {
throw new \Exception('参数错误');
}
$role->name = $post['name'];
$role->description = $post['description'];
$role->ruleName = empty($post['rule_name']) ? null : $post['rule_name'];
$role->data = empty($post['data']) ? null : $post['data'];
if ($auth->add($role)) {
Yii::$app->session->setFlash('info', '添加成功');
}
}
return $this->render('_createitem');
}
原理:
所谓的分配权限就是将给用户分配是否可以访问控制器的权限,确认要分配的对象 实则是指定表的user_id对应的item_name值
具体如何做呢?? 看这里->
/* 分配权限 */
public function actionAssignitem($name)
{
//获取到角色
$name = htmlspecialchars($name);
$auth = Yii::$app->authManager;
//获取到当前角色的信息
$parent = $auth->getRole($name);
if (Yii::$app->request->isPost) {
$post = Yii::$app->request->post();
if (Rbac::addChild($post['children'], $name)) {
Yii::$app->session->setFlash('info', '分配成功');
}
}
$children = Rbac::getChildrenByName($name);
//获取当前用户的
$roles = Rbac::getOptions($auth->getRoles(),$parent);
//获取当前用户拥有的权限
$permissions = Rbac::getOptions($auth->getPermissions(), $parent);
return $this->render('_assignitem', ['parent' => $name, 'roles' => $roles, 'permissions' => $permissions, 'children' => $children]);
}
RBAC~~规则指定,更高级的权限指定
接下来,不得不谈谈rbac的规则,这又是个什么东西呢?? 所谓的规则 其实就是对用户的权限的额外限制
原理:
通过定义规则类,添加用户的时候指定规则名称 就可以实现对用户的权限的额外限制,
数据表中,data字段就是实例化的自定义规则类对象
比如我们定义这样一个自定义规则类
/*实现分类只能由添加者删除*/
class AuthorRule extends Rule
{
public $name = "isAuthor";
//当前的用户,权限,额外的参数
public function execute($user, $item, $params)
{
$action = Yii::$app->controller->action->id;
//对delete方法 进行额外限制
if ($action == 'delete') {
//获取到当前分类是由那个用户添加的 不允许其他用户删除
$cateid = Yii::$app->request->get("id");
$cate = Category::findOne($cateid);
return $cate->adminid == $user;
}
return true;
}
}
我们如何创建这个规则到数据表中呢??
/*创建规则*/
public function actionCreaterule()
{
if (Yii::$app->request->isPost) {
$post = Yii::$app->request->post();
if (empty($post['class_name'])) {
throw new \Exception('参数错误');
}
//指定当前的规则命名空间
$className = "app\\models\\". $post['class_name'];
if (!class_exists($className)) {
throw new \Exception('规则类不存在');
}
$rule = new $className;
//使用authManager组件将当前的规则类 保存到数据库
if (Yii::$app->authManager->add($rule)) {
Yii::$app->session->setFlash('info', '添加成功');
}
}
return $this->render("_createrule");
}
这样再添加用户的时候,就可以指定规则,进而实现对更加高级的指定权限
到这里,基本完成了用户创建,权限分配,及规则指定,希望可以帮到大家~~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。