一种很好的访问控制模式

时间:2014-09-13 00:00:51

标签: zend-framework2 aop acl rbac

我一直在研究Zend Framework 2应用程序。它有一个包装模型层的服务层。控制器调用服务层,该层与模型和映射器进行通信。

我发现的问题是访问控制需要付出很多努力,包括测试工作。该应用程序使用社交图,因此访问规则非常复杂。例如,如果用户A想要访问关于用户B的特定类别的信息,则他们可能需要是某种类型的用户,并且可能需要与B的特定数量的连接。

某些访问规则似乎属于模型层。要将它们放在服务层中,我必须将模型功能泄漏到服务中。其他人似乎属于服务层,例如,从映射器中提取对象集合的那些(映射器没有访问控制的概念)。

有没有人有过这种访问控制复杂性的经验?并不是系统不起作用,只是50%的代码(以及测试,模拟等)被访问控制所占用。有更简单的方法吗?

我考虑过驱动访问控制事件 - 每个安全方法都会触发一个事件,如果需要,该事件的监听器会抛出异常。 (我不会在测试时附加听众,所以我节省了大约一半的测试用例)。有没有人有这方面的经验?

我很久以前尝试过ACL和RBAC,但找不到满意的解决方案。大约一年前我研究过XACML,但它看起来有些过分,即便如此,我也不确定它会解决这些问题。

1 个答案:

答案 0 :(得分:1)

由于我是面向方面的PHP编程专家,我认为您应该看一下这个范例,因为它是由Xerox PARC设计的,用于解决面向对象代码中的交叉问题。

关于访问控制的问题描述了典型的分散功能,你认为这个代码在任何地方都是重复的,这是正确的,因为传统的面向对象范式并不能解决如何优雅地做到这一点。

OOP的可能解决方案是创建可以检查访问权限的装饰器。另一种方法是将类的每个API方法修改为trigger an event,并准备一个安全处理程序,在事件分派期间检查访问权限。两种解决方案都不完美。

在JAVA世界中,AOP已被用于访问控制很长时间(例如,使用AspectJ,Spring)。我开发了Go!用于PHP的AOP框架,它是Spring框架的移植版本,由AOP Alliance接口提供支持。

让我们看一下如何用AOP做到这一点。主类包含几个具有域逻辑的业务方法:

class MyService {
    public function updateProfile() {...}
    public function deleteProfile() {...}
} 

然后我们使用doctrine annotation @Secured(PROFILE_EDIT)标记我们的方法,并定义一个方面,它将在源代码中的任何地方用这个注释拦截方法的执行:

use Go\Aop\Aspect;
use Go\Aop\Intercept\MethodInvocation;
use Go\Lang\Annotation\Before;

/**
 * Security aspect
 */
class SecurityAspect implements Aspect
{
    /**
     * This advice intercepts an execution of secured methods
     *
     * Logic is pretty simple: we check an access rights before original method and
     * then invoke original method or throw an exception.
     *
     * @param MethodInvocation $invocation Invocation
     *
     * @Before("@annotation(Demo\Annotation\Secured)")
     */
    public function beforeSecuredMethod(MethodInvocation $invocation)
    {
        $right = $invocation->getMethod()->getAnnotation('Demo\Annotation\Secured')->value;
        if (!Security::isGranted($right)) {
            throw new AuthorizationException("Access denied. {$right} is required.");
        }
    }
}

您可以阅读有关logging with AOP的更详细的文章,了解如何实施授权。我还有working demo of logging aspect for Zend Framework2来检查效果和more examples