在哪里放置“非授权”访问控制逻辑,似乎不适合ACL?

时间:2011-01-22 11:09:59

标签: zend-framework acl web-applications

我想知道“非授权”访问控制逻辑,例如。人们只能在顶级待办事项上添加儿童待机。它似乎不适合ACL,它似乎更适用于身份验证/授权访问控制逻辑?

我是否全部放入ACL?我必须以某种方式显示不同的错误信息,例如。 “你无法执行此操作”而不是“你没有足够的权限来执行此操作”...我该怎么做?

2 个答案:

答案 0 :(得分:0)

您应该处理访问列表对象外部的访问逻辑。我为此创建了一个frontController插件:

class Soflomo_Controller_Plugin_Access extends Zend_Controller_Plugin_Abstract
{
    public function dispatchLoopStartup (Zend_Controller_Request_Abstract $request)
    {
        if (!$this->_isAllowed($request)) {
            throw new Zend_Controller_Action_Exception('No permission', 403);
        }
    }

    protected function _isAllowed (Zend_Controller_Request_Abstract $request, $permission = 'view')
    {
        $acl = new Acl(); // Here your logic to fetch a (cached) ACL
        $role = new User(); // Here your logic to fetch role
        $resource = new Page(); // Here your logic to fetch resource

        return $acl->hasRole($role)
            && $acl->has($resource)
            && $acl->isAllowed($role, $resource, $permission);
    }
}

在这种情况下,我明确检查角色和资源的存在。这是因为我的数据库中只有ACL规则,其中角色可以访问资源。所有其他情况(当用户没有访问权限时)我将其从数据库中删除。

当你有不同的逻辑时,或许可以检查$acl->isAllowed($role, $resource, $permission);并将$acl->hasRole()$acl->has()退出。

错误处理程序

我抛出一个带有错误代码403的Zend_Controller_Action_Exception,但是如果你没有捕获到特定的代码,它将看起来像一个正常的应用程序错误。因此我在ErrorHandler frontController插件中添加了另一个常量EXCEPTION_NO_PERMISSION并将其添加到switch语句中:

case 'Zend_Controller_Action_Exception':
if (404 == $exception->getCode()) {
    $error->type = self::EXCEPTION_NO_ACTION;
} elseif (403 == $exception->getCode()) {
    $error->type = self::EXCEPTION_NO_PERMISSION;
} else {
    $error->type = self::EXCEPTION_OTHER;
}
break;

然后,您可以在ErrorController中获取错误类型EXCEPTION_NO_PERMISSION

答案 1 :(得分:0)

最常见的方法是处理控制器插件中的逻辑。这在大多数情况下效果很好, 但我建议将逻辑存储在模型中。

ACL也是一个模型。

任何模型/表单/类只需提供Zend_Acl_Resource_Interface方法即可实现getResourceId(): e.g。

abstract class My_Form_Acl extends Zend_Form {

    public function __construct() {
       // ...
       parent::__construct();
    }

    public function getResourceId()
    {
       return get_class($this);
    }
}