ZF2 - BjyAuthorize - 如何从数据库中获取规则和保护

时间:2013-08-16 02:00:03

标签: zend-framework2 doctrine zend-db bjyauthorize

我正在使用BjyAuthorize和Zend Framework2来实现授权,并且能够成功地集成来自数据库的角色。现在我想从数据库表中获取规则和保护。我怎么能这样做?

2 个答案:

答案 0 :(得分:7)

最简单的方法和"技巧"这是真的:

  1. 将您的规则和警卫变为与示例配置中显示的相同的数组格式。因此,在从数据库中读取记录后,无论您的原始数据库数据是什么格式,都要处理它以匹配与配置中相同的保护格式。 (我的答案详细说明了如何使用Doctrine ORM,但也应该让你了解其他数据库引擎。只需用你的fave数据库引擎替换"数据库读取"操作)

    < / LI>
  2. BjyAuthorize\Guard\Controller内部将您已编写的规则注入BjyAuthorize所需的正确格式(因为您这样做了),进入YOUR_MODULE_NAME\Factory\DoctrineControllerGuardAdapterFactory。 Bjy的控制器会将这些规则视为配置*,并且不会怀疑任何差异。

  3. 退一步享受!

  4. 这是您需要在自己的模块中编写的构造:

    namespace YOUR_MODULE_NAME\Factory;
    
    /**
     * See "How and where exactly to register the factory" in ZF2 config
     * below in my answer.
     */
    class [Custom]ControllerGuardAdapterFactory 
    {
        public function createService(ServiceLocatorInterface $serviceLocator)
        {
            /**
             * Retrieve your rules from favorive DB engine (or anything)
             *
             * (You may use $serviceLocator to get config for you DB engine)
             * (You may use $serviceLocator to get your DB engine)
             * (You may use $serviceLocator to get ORM Entity for your DB engine)
             * (Or you may hack your DB connection and retrieval in some other way)
             *
             * Hell, you may read them from a text file using PHP's file() method
             * and not use $serviceLocator at all
             *
             * You may hardcode the rules yourself right here for all that matters
             */            
            $rules = ... //array(...);
    
    
            /** 
             * Inject them into Bjy's Controller
             *
             * Rules must be in the same format as in Bjy config, or it will puke.
             * See how ['guards'][\BjyAuthorize\Guard\Controller::class] is constructed 
             * in Bjy configuration for an example
             */             
            return new \BjyAuthorize\Guard\Controller($rules, $serviceLocator); 
        }
    }
    

    现在观察并观察这是多么令人难以置信的复杂化! (以Bjy自己的机制为模型)

    这主要是ZF2,OO&amp; Bjy&#34;配置地狱&#34;,伙计们,没有什么特别的。欢迎来到ZF2和Bjy以及ORM配置地狱。不客气。

    详细解答 - 如何实施?

    编写一个 adapter 工厂,它从数据库中读取规则,然后将它们注入BjyAuthorize's Controller Guard。效果与从['guards'][\BjyAuthorize\Guard\Controller::class]

    中读取规则的效果相同

    <强>什么吗

    BjyAuthorize's Controller Guard的工作方式是采用某种格式的规则(为['guards']['BjyAuthorize\Guard\Controller']指定的格式),然后使用规则填充ACL。它还会根据您的规则计算资源,并将这些资源加载到ACL中。如果没有,那么您必须编写自己的资源提供程序。

    所以任务变为:

    • 从数据库加载规则并将规则转换为BjyAuthorize期望的格式。这可以在您自己的规则提供程序much like this one中完成。
    • 您可以使用工厂从module.config.php文件加载特定的数据库和存储类配置数组。我把我放在['guards']['YOUR_MODULE_NAME_controller_guard_adapter']下面。
    'guards' => array(
            'YOUR_MODULE_NAME_controller_guard_adapter' => array(
                'object_manager' => 'doctrine.entity_manager.orm_default',
                'rule_entity_class' => 'YOUR_MODULE_NAME\Entity\ObjectRepositoryProvider'
            )
    )
    

    示例实施细节(来自评论中的Q / A)

    更多关于&#34;将规则注入Controller&#34;的最后一点。基本上有两个步骤:1)确保你已经(或将)以某种方式生成你的规则(这是艰难的一步)。 2)将这些规则注入控制器(这是更容易的步骤)。实际注射就像这样完成

    $rules = __MAGIC__;  //get rules out of somewhere, somehow.
    return new Controller($rules, $serviceLocator); //$rules injection point
    

    请参阅下面的代码块以了解我自己的实现,其中块中的最后一行是我在上面给出的行。

    namespace YOUR_MODULE_NAME\Factory;
    
    use BjyAuthorize\Exception\InvalidArgumentException;
    use Zend\ServiceManager\FactoryInterface;
    use Zend\ServiceManager\ServiceLocatorInterface;
    use YOUR_MODULE_NAME\Provider\Rule\DoctrineRuleProvider;    //this one's your own
    use BjyAuthorize\Guard\Controller;
    
    class DoctrineControllerGuardAdapterFactory implements FactoryInterface
    {
        public function createService(ServiceLocatorInterface $serviceLocator)
        {
            //just setting up our config, move along move along...
            $config = $serviceLocator->get('Config');
            $config = $config['bjyauthorize'];
    
            //making sure we have proper entries in our config... 
            //move along "nothing to see" here....
            if (! isset($config['guards']['YOUR_MODULE_NAME_controller_guard_adapter'])) {
                throw new InvalidArgumentException(
                    'Config for "YOUR_MODULE_NAME_controller_guard_adapter" not set'
                );
            }
    
            //yep all is well we load our own module config here
            $providerConfig = $config['guards']['YOUR_MODULE_NAME_controller_guard_adapter'];
    
            //more specific checks on config
            if (! isset($providerConfig['rule_entity_class'])) {
                throw new InvalidArgumentException('rule_entity_class not set in the YOUR_MODULE_NAME guards config.');
            }
    
            if (! isset($providerConfig['object_manager'])) {
                throw new InvalidArgumentException('object_manager not set in the YOUR_MODULE_NAME guards config.');
            }
    
            /* @var $objectManager \Doctrine\Common\Persistence\ObjectManager */
            $objectManager = $serviceLocator->get($providerConfig['object_manager']);
    
            //orp -- object repository provider
            //here we get our class that preps the object repository for us
            $orp=new DoctrineRuleProvider($objectManager->getRepository($providerConfig['rule_entity_class']));
    
            //here we pull the rules out of that object we've created above
            //rules are in the same format BjyAuthorize expects
            $rules=$orp->getRules();
    
            //here pass our rules to BjyAuthorize's own Guard Controller.  
            //It will not know the difference if we got the rules from Config or from Doctrine or elsewhere,  
            //as long as $rules are in the form it expects.
            return new Controller($rules, $serviceLocator); 
        }
    }
    

    DoctrineRuleProvider

    namespace YOUR_MODULE_NAME\Provider\Rule;
    
    use Doctrine\Common\Persistence\ObjectRepository;
    use BjyAuthorize\Provider\Rule\ProviderInterface;
    
    /**
     * Guard provider based on a {@see \Doctrine\Common\Persistence\ObjectRepository}
     */
    class DoctrineRuleProvider implements ProviderInterface
    {
        /**
         * @var \Doctrine\Common\Persistence\ObjectRepository
         */
        protected $objectRepository;
    
        /**
         * @param \Doctrine\Common\Persistence\ObjectRepository $objectRepository            
         */
        public function __construct(ObjectRepository $objectRepository)
        {
            $this->objectRepository = $objectRepository;
        }
    
        /**
         * Here we read rules from DB and put them into an a form that BjyAuthorize's Controller.php understands
         */
        public function getRules()
        {
            //read from object store a set of (role, controller, action) 
            $result = $this->objectRepository->findAll();
    
            //transform to object BjyAuthorize will understand
            $rules = array();
            foreach ($result as $key => $rule)
            {
                $role=$rule->getRole();
                $controller=$rule->getController();
                $action=$rule->getAction();            
    
                if ($action==='all')    //action is ommitted
                {
                    $rules[$controller]['roles'][] = $role;
                    $rules[$controller]['controller'] = array($controller);
                }
                else
                {
                    $rules[$controller.':'.$action]['roles'][]=$role;
                    $rules[$controller.':'.$action]['controller']=array($controller);
                    $rules[$controller.':'.$action]['action']=array($action);
                }                       
            }    
    
            return array_values($rules);
        }
    }
    

    问:如何以及在何处准确注册工厂DoctrineControllerGuardAdapterFactory

    答:尝试此路径:module\YOUR_MODULE_NAME\config\module.config.php并拥有

    'service_manager' => array(
        'factories' => array(
            'YOUR_MODULE_NAME_controller_guard_adapter' => \YOUR_MODULE_NAME\Factory\DoctrineControllerGuardAdapterFactory::class
        )
    )
    
    • 注意:YOUR_MODULE_NAME=>符号左侧的内容是&#34;键&#34;,可以是您想要的任何内容。 Bjy中的约定是它类似于实际的类名和路径。 =>右侧的内容是您要使用此密钥调用的类的实际完全限定名称空间。

答案 1 :(得分:1)

基本上你必须自己编写Provider

查看不同的RoleProvider。每个RoleProvider都会实现Provider\Role\ProviderInterface。当你想要实施警卫和规则时,必须做同样的事情。您进入特定目录Provider\RuleProvider\Resource并检查特定ProviderInterface

通过这种方式,您可以编写自己的实现接口的类,然后通过配置告诉BjyAuthorize使用您的提供者类。

就卫兵而言,我确实认为尚无法从数据库中创建这些内容。您必须修改/ PR模块本身才能实现这一目标。