1

我设置了角色、任务和操作层次结构,并分配给用户,操作镜像控制器:操作。

docs中,如果我想检查用户是否有权访问操作,我会检查,例如:

if(Yii::app()->user->checkAccess('createPost'))

这给人的印象是我必须在每个操作中手动添加代码以检查用户是否被授权到相应的角色。我是否遗漏了某些东西-肯定有一种方法可以为每个动作自动执行此操作。

我可以扩展基本 Controller 类并添加一些东西(在 preFilter 中?)使用 Yii::app()->controller 和 Yii::app()->controller->action 来生成角色,然后检查用户被授权担任该角色。

但我确定一定有办法做到这一点?

我知道 accessRules 过滤器允许您传递角色,但这似乎违背了拥有角色>任务>操作层次结构的目的,并且必须为每个操作分配这样的规则几乎与在每个函数中进行检查一样糟糕第一名。

是否还有其他一些我缺少的选项会自动检查执行例如 /item/delete 的用户是否有权执行“item:delete”操作(或 DB AuthItem 表中预期的任何格式)?

编辑
在数据库 RBAC 旁边澄清我的 accessRules 问题:

我在我的数据库中定义了一个角色结构 - 多个角色,每个角色都被授权执行多个任务,这些任务又由细粒度操作组成(例如角色“读者”可能被授权执行任务“浏览帖子”,这是'post/index' 和 'post/view')。然后我将一个用户分配给一个角色,该角色授予他们对该角色的任务以及这些任务中的操作的权限。如果我随后为控制器操作(即操作)调用user->checkAccess ,它会在数据库中检查用户是否已获得角色的授权,该角色包含包含该操作的任务。

但是,如果我遍历每个控制器并定义每个操作被授权的角色,我正在复制我已经在数据库中完成的工作,可能会有冲突的规则。

4

3 回答 3

2

过滤器似乎起到了作用。

假设您在 protected/components/Controller.php 中定义了一个基本控制器,请将以下函数添加到它以定义一个过滤器。如果由于某种原因您没有基本的 Controller 类,请在单独的类中定义过滤器,如Controller 文档中所述。无论如何,这样做可能会更好(更可重用)。

public function filterAccessControl($filterChain)
{
    $controller = Yii::app()->controller->id;
    $action = Yii::app()->controller->action->id;

//The RBAC admin module I'm using creates entries for operations as, e.g. Post:Create
// You may need to change this to match whatever entry format you have in your AuthItem table
    $operation = ucfirst($controller) . ':' . ucfirst($action);
    Yii::log('Checking auth for user: ' . Yii::app()->user->id. ' to operation: ' . $operation, 'info');

    if(Yii::app()->user->checkAccess($operation))
    {
        Yii::log('User authorised', 'info');
        $filterChain->run();
        return true;
    }
    else
    {
        Yii::log('Unauthorised user!!!!!', 'info');
        throw new CHttpException(401, 'You are not authorized to perform this action.');            
        return false;
    }   
}

(我使用RBAM来管理数据库中的 Auth 表,它将操作名称存储为 ControllerName:ActionName,因此是 ucfirst)。

要为每个控制器中的每个操作运行此过滤器,请再次在 Controller.php 中添加filters()函数来应用过滤器:

public function filters()
{
    return array(
   'accessControl',
);
}

一些警告:

  • 如果您的任何控制器中有现有过滤器,则需要在此处应用此过滤器,因为该控制器过滤器()函数将覆盖此过滤器
  • 无论如何,在每个控制器中单独执行它可能会更安全,因为如果有必要,您可以限制过滤器适用的操作,如果出于某种原因您想要一些例外。另外,如果您只在此处执行此操作,然后忘记并稍后将其他过滤器添加到某个控制器,您将失去对它们的访问控制!
  • 在执行此操作之前,请确保您已在authManager配置中配置了默认来宾角色,并且该角色可以访问 /site/login。否则您将无法登录!(如果发生这种情况,请禁用过滤器,直到您将其整理出来)
于 2013-11-15T08:33:28.517 回答
0

使用 yii-auth 怎么样?https://github.com/Crisu83/yii-auth

你可以避免检查每个地方 -if(Yii::app()->user->checkAccess('createPost')) 并使用类似的东西

public function filters()
{
  return array(
    array('auth.filters.AuthFilter'),
  ),
}
于 2013-11-15T07:29:21.073 回答
0

我的回答可能不会对这个问题有太多新的认识:

最终,应用程序无法猜测允许谁执行每个操作。你必须告诉 Yii 谁被允许做什么动作——这种方式(可能更长)或其他方式(可能更短)。

您可以通过“漫长的方式”来执行此操作,即在每个操作方法的开头添加一个“checkAccess()”,如果用户没有访问权限,则使用自定义消息做出反应。请注意,这种方式即使很长,也是冗长而干净的,这会导致代码更容易维护。

正如您所指出的,您还可以通过“ accessRules ”方法使用“访问控制过滤器”。这更短,但对局外人来说不太清楚(可能是你,在远离代码的那个心理区域几个月后),因此代码难以维护,恕我直言。

我确实想指出,将“访问控制过滤器”与 RBAC 一起使用不会与非常好的权限层次结构相矛盾或破坏。请记住,这个层次结构由相互继承的角色组成,每个角色都包含任务和可能的操作(YMMV。我通常会做相互继承的角色,每个角色都是由任务“组成”的,其中一些具有 bizrules) . 如果您可以详细说明,为什么您认为这将“破坏具有角色>任务>操作层次结构的目的”,这对于本次讨论可能是富有成果的。

于 2013-11-15T06:54:48.247 回答