我正在考虑使用Zend_ACL。但是,对我而言,您似乎创建了角色,然后将这些角色授予他们可以访问或无法访问的控制器和操作。
然而,对我而言似乎相当有限。我之前创建了一个用户权限系统,我存储了user_id,模块,控制器和他们可以访问的操作,但我从来没有给他们一个组。因此,每个模块,每个控制器的每个用户,每个操作基于他们可以访问的内容。
原来如此!我想知道我是否希望减少群组的限制,我应该为用户提供一个组并默认设置这些组权限。然后加载我的用户特定角色并覆盖默认组设置的角色:那你们会怎么做?
答案 0 :(得分:3)
您绝不仅限于使用角色系统来表示Zend_Acl
中的群组。
例如:
在一个应用程序中,我有我的基本用户对象,实现Zend_Acl_Role_Interface
,在这种情况下返回一个特定于用户的字符串。为简单起见,我们只需说user-1
之类的内容,其中数字部分是用户的唯一ID。
初始化用户对象时,它会将自身添加到ACL中,其中特定于用户的角色继承自更通用的角色(类似于组)。
if(!$acl->hasRole($this)) {
$acl->addRole($this, $this->role); // Let's say role == 'member' here
}
这允许您设置父角色的一般规则(或角色,您可以将数组作为第二个参数传递给addRole,以拥有多个父级。另外,请记住角色在树的所有方向都有一个沿袭,所以在这种情况下,父角色本身也可能有父角色。)
因此,为了说明这里的灵活性,让我们假设这个基本的ACL设置(这是理论上的,我只是为了这个答案的目的而写它):
$acl->addRole('guest');
$acl->addRole('member', 'guest');
$acl->allow('guest', 'comments', 'read');
$acl->allow('member', 'comments', 'write');
$user = $My_User_Model->find(1);
$acl->allow($user, 'comments', 'moderate');
$acl->isAllowed($user, 'comments', 'read'); // true
$acl->isAllowed($user, 'comments', 'write'); // true
$acl->isAllowed($user, 'comments', 'moderate'); // true
$acl->isAllowed('member', 'comments', 'moderate'); // false
等等......
Zend Framework组件的优点在于,您并不仅限于以特定方式使用它们。是的,虽然这有时令人生畏,并且往往需要花费更多的时间投入初始规划和实施,但从长远来看,这是很好的。
另外,就个人而言,我不喜欢将ACL权限直接映射到控制器/动作构造。但这是一个完全不同的对话。
答案 1 :(得分:1)
当我开始使用Zend_Acl
时,我问very similar question。我的帖子用代码列出了我的解决方案它可能对你有帮助。 :)
答案 2 :(得分:0)
你走在正确的轨道上。
没有严格定义的“组”或“用户”的概念。
你只有角色。您可能拥有“编辑器”这样的角色,可以访问某些资源(如特定操作,甚至某些“文章”对象)。您可能还有像user_1234这样的角色,可能有其他规则。
您可以为ID为1234的用户提供这两个角色。
答案 3 :(得分:0)
回复上述内容(我的回答很长)
是的,我不是那样做的忠实粉丝。我宁愿为特定用户加载一个数组:
$item['Movie'] = 1;
$item['Movie']['manage']['edit'] = 0;
然后执行一个插件,将这些权限(从数据库加载到数组中)加载当前模块/控制器/操作并检查。
if (isset($item[$module]) && $item[$module] == 1) {
if (isset($item[$module][$controller][$action]) && $item[$module][$controller][$action] == 0) {
return false;
}
return true;
} else {
return false;
}
然后在我的bootstrap中,如果它为false,则抛出异常。 (请记住,这是针对我网站的管理区域,而不是前端,所以我不会对一般用户访问感到讨厌。
此外,我将该数组传递给视图,并在链接上执行简单的if语句:
<?php if ($this->userPermission['Movie']['manage']['edit'])) { ?>
<a href="/administration/Movie/manage/edit/id/1">Edit Movie</a><?php } ?>
缺点是如果该方法改变了控制器,我必须编辑模板。但是我从我读过的教程中看不到Zend_ACL视图的含义,所以我不确定它与我在那里做的有很大不同。
答案 4 :(得分:0)
感谢您的反馈,但我决定创建自己的。如果有人有兴趣:
public function verify($controller=NULL, $action='index', $module='administration') {
if ((isset($this->object[$module]['all']) && is_string($this->object[$module]['all'])) || isset($this->object[$module][$controller][$action]) || (isset($this->object[$module][$controller]) && is_string($this->object[$module][$controller]))) {
return true;
}
}
public static function check($values) {
$module = $values['module'] ? $values['module'] : 'administration';
$controller = $values['controller'] ? $values['controller'] : 'index';
$action = $values['action'] ? $values['action'] : 'index';
$user_id = $values['user_id'];
$db = Zend_Registry::get('dbAdapter');
$query = $db->prepare("
SELECT *
FROM `".self::table_name."`
WHERE
(
(`module` = :module AND `controller` = :controller AND `action` = :action) OR
(`module` = :module_2 AND `controller` = :controller_2 AND `action` = '') OR
(`module` = :module_3 AND `controller` = '' AND `action` = '')
)
AND enabled = 1
AND user_id = :user_id
");
$query->bindValue('module', $module);
$query->bindValue('module_2', $module);
$query->bindValue('module_3', $module);
$query->bindValue('controller', $controller);
$query->bindValue('controller_2', $controller);
$query->bindValue('action', $action);
$query->bindValue('user_id', $user_id);
$query->execute();
$item = $query->fetch(PDO::FETCH_OBJ);
$query->closeCursor();
if (is_object($item)) {
return $item;
} else {
throw new exception("Could not load user permission for this page ($module, $controller, $action)");
}
}
并在视图中:
<?php if ($this->user_permissions->verify('movie')) { ?>
<li class="parent">
<img src="/design/images/icon/dvd.png" /> <span class="highlighter"><a href="/administration/movie/index">Movie</a></span>
<?php if ($this->user_permissions->verify('movie', 'add')) { ?>
| <a href="/administration/movie/add">Add</a>
<?php } ?>
<?php if ($this->user_permissions->verify('movie', 'featured')) { ?>
<ul>
<li>
<img src="/design/images/icon/order.png" /> <a href="/administration/movie/featured">Order Featured</a>
</li>
</ul>
<?php } ?>
</li>
<?php } ?>