我正在考虑使用 Zend_ACL。但是,在我看来,您似乎创建了角色,然后将这些角色授予控制器和他们可以或不能访问的操作的权限。
然而,对我来说,这似乎相当有限。过去我创建了一个用户权限系统,在其中存储了 user_id、模块、控制器和他们可以访问的操作,但是我从未给他们一个组。因此,每个用户、每个模块、每个控制器、每个操作都基于他们可以访问的内容。
所以!我想知道我是否想减少组的限制,我应该给用户一个组并默认设置这些组权限。然后加载我的用户特定角色并覆盖默认组设置的角色:你们会这样做吗?
我正在考虑使用 Zend_ACL。但是,在我看来,您似乎创建了角色,然后将这些角色授予控制器和他们可以或不能访问的操作的权限。
然而,对我来说,这似乎相当有限。过去我创建了一个用户权限系统,在其中存储了 user_id、模块、控制器和他们可以访问的操作,但是我从未给他们一个组。因此,每个用户、每个模块、每个控制器、每个操作都基于他们可以访问的内容。
所以!我想知道我是否想减少组的限制,我应该给用户一个组并默认设置这些组权限。然后加载我的用户特定角色并覆盖默认组设置的角色:你们会这样做吗?
您绝不限于使用角色系统来表示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 权限直接映射到控制器/操作构造。但那是完全不同的对话。
你在正确的轨道上。
没有严格定义的“组”或“用户”的概念。
你只有角色。你可能有一个像“编辑”这样的角色,它可以访问某些资源(比如一个特定的动作,甚至是一些“文章”对象)。您可能还有一个像 user_1234 这样的角色,它可能有额外的规则。
您会将这两个角色都分配给 id 为 1234 的用户。
回复上述(我的回复很长)
是的,我不喜欢那样做。我宁愿为该特定用户加载一个数组:
$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;
}
然后在我的引导程序中,如果它为假,则抛出异常。(请记住,这是针对我网站的管理区域,而不是前端,所以我对一般用户访问权限并不在意。
此外,我将该数组传递到视图并在链接上执行简单的 if 语句:
<?php if ($this->userPermission['Movie']['manage']['edit'])) { ?>
<a href="/administration/Movie/manage/edit/id/1">Edit Movie</a><?php } ?>
不利的一面是,如果该方法更改了控制器,我将不得不编辑模板。但是,我从我读过的教程中没有看到 Zend_ACL 视图的实现,所以我不确定它是否与我在那里做的有很大不同。
感谢您的反馈,但我决定创建自己的。如果有人感兴趣:
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 } ?>