【问题标题】:ZF2 / doctrine ORM authentication different EntityZF2/学说ORM认证不同Entity
【发布时间】:2015-03-11 11:39:59
【问题描述】:

在我的应用程序(ZF2 / ORM)中,我有 3 个实体(具有单表继承)

用户

所有者扩展用户

代理扩展用户

我想使用 3 个实体进行一次身份验证(登录) 学说.authenticationservice.orm_default

module.config.php

 //other doctrine config 
    'authentication' => array(
        'orm_default' => array(
            'object_manager' => 'Doctrine\ORM\EntityManager',
            'identity_class' => 'Application\Entity\User',
            'identity_property' => 'email',
            'credential_property' => 'password',
            'credential_callable' => function(User $user, $passwordGiven) {
                return $user->getPassword() == md5($passwordGiven);
            },
        ),
    ),

以及登录过程

//登录控制器.php

// ..data validation 
            $this->authService = $this->getServiceLocator()->get('doctrine.authenticationservice.orm_default');
            $AuthAdapter = $this->authService->getAdapter();
            $AuthAdapter->setIdentity($this->request->getPost('email'));
            $AuthAdapter->setCredential(md5($this->request->getPost('password')));
            $result = $this->authService->authenticate();

            if($result->isValid()){
                $identity = $result->getIdentity();
                //continue                   
            }

如何在不关心对象类型的情况下完成此过程, 当我尝试使用代理的电子邮件登录时,我收到此错误

可捕获的致命错误:传递给 Application\Module::{closure}() 的参数 1 必须是 User 的实例,给定的 Application\Entity\Owner 的实例

【问题讨论】:

    标签: authentication orm doctrine-orm zend-framework2


    【解决方案1】:

    您提到的错误是由于类型提示:

    function(User $user) {
    

    这让我相信您的配置文件中缺少命名空间声明;在这种情况下,您可以添加它或使用 FQCN。

    function(\Application\Entity\User $user) {
    

    不过,我认为这实际上不是问题所在。您只能使用原则身份验证定义一个“identity_class”(适配器将使用它从实体管理器加载实体)。如果您有多个实体类,则无法使用一个适配器对每个实体类进行测试。

    但是,配置实际上只是创建了一个新的身份验证适配器,特别是DoctrineModule\Authentication\Adapter\ObjectRepository。一种解决方案是创建多个ObjectRepository 适配器,每个适配器都为不同的实体配置正确的配置,然后在Zend\Authentication\AuthenticationService 上调用authenticate() 时循环遍历它们。

    例如:

    public function methodUsedToAutheticate($username, $password)
    {
        // Assume we have an array of configured adapters in an array
        foreach($adapters as $adapter) {
    
            $adapter->setIdentity($username);
            $adapter->setCredential($password);
    
            // Authenticate using the new adapter
            $result = $authService->authenticate($adapter);
    
            if ($result->isValid()) {
                // auth success
                break;
            }
        }
        return $result; // auth failed
    }
    

    如前所述,原则配置不允许多个适配器,因此您需要手动创建它们并删除当前配置。

    另一个例子

    public function getServiceConfig()
    {
        return [
            'factories' => [
                'MyServiceThatDoesTheAuthetication' => function($sm) {
    
                    $service = new MyServiceThatDoesTheAuthetication();
    
                    // Assume some kind of api to add multiple adapters
                    $service->addAuthAdapter($sm->get('AuthAdapterUser'));
                    $service->addAuthAdapter($sm->get('AuthAdapterOwner'));
                    $service->addAuthAdapter($sm->get('AuthAdapterAgent'));
    
                    return $service;
                },
                'AuthAdapterAgent' => function($sm) {
                    return new DoctrineModule\Authentication\Adapter\ObjectRepository(array(
                        'object_manager'      => $sm->get('ObjectManager'),
                        'identity_class'      => 'Application\Entity\Agent',
                        'identity_property'   => 'email',
                        'credential_property' => 'password'
                    ));
                },
                'AuthAdapterOwner' => function($sm) {
                    return new DoctrineModule\Authentication\Adapter\ObjectRepository(array(
                        'object_manager'      => $sm->get('ObjectManager'),
                        'identity_class'      => 'Application\Entity\Owner',
                        'identity_property'   => 'email',
                        'credential_property' => 'password'
                    ));
                },
                // etc...
            ],
        ];
    }
    

    希望这能给您一些关于需要什么的想法。

    最后,如果您考虑使用其他模块,ZfcUser already has a 'chainable adapter' 实际上执行上述操作(但使用事件管理器),因此即使您不使用它也可能值得一看。

    【讨论】:

    • 非常感谢,非常有用的解决方案:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-04
    • 1970-01-01
    相关资源
    最近更新 更多