ZF2:Zend_Auth和Doctrine如何绕过setCredentialValue检查,即不需要密码检查时

时间:2015-10-29 07:19:20

标签: php zend-framework zend-framework2 doctrine zend-auth

我已使用Zend_Auth&已实施登录模块Doctrine,并且按预期工作正常,现在我已经在模块中实现了Social login,在这种情况下我需要绕过Password检查,因为在这种情况下不需要密码一旦用户通过第三方提供商(例如 Facebook 等)进行验证。

所以我在社交登录尝试的情况下按功能修改了

controller

$authService = $this->getServiceLocator()->get('Zend\Authentication\AuthenticationService');
$adapter = $authService->getAdapter();
$adapter->setIdentityValue($userProfile->email);
$adapter->setCredentialValue('NA'); //  <----- I have used "NA" to notify its an social login

并在module.config.php

'doctrine' => array(
        'authentication' => array(
            'orm_default' => array(
                'object_manager' => 'Doctrine\ORM\EntityManager',
                'identity_class' => 'Account\Entity\Account',
                'identity_property' => 'username',
                'credential_property' => 'password',
                'credential_callable' => function(Entity\Account $user, $passwordGiven) {
                    if($passwordGiven == 'NA')
                        return true;
                    else
                        return md5($passwordGiven) == $user->getHpassword();
                },
            )
        ),

它的工作正常,但我不确定这是正确的方法吗?任何建议或更可行的方法。

1 个答案:

答案 0 :(得分:1)

学说authentication课程已注册here in the module.config.php from DoctrineModule

'doctrine' => array(
    'doctrine_factories' => array(
        'cache'                 => 'DoctrineModule\Service\CacheFactory',
        'eventmanager'          => 'DoctrineModule\Service\EventManagerFactory',
        'driver'                => 'DoctrineModule\Service\DriverFactory',
        'authenticationadapter' => 'DoctrineModule\Service\Authentication\AdapterFactory',
        'authenticationstorage' => 'DoctrineModule\Service\Authentication\StorageFactory',
        'authenticationservice' => 'DoctrineModule\Service\Authentication\AuthenticationServiceFactory',
    )
)

您可以使用自定义工厂轻松覆盖这些配置。

我不确定管理所有这些的最佳方法是什么,因为我不知道您的社交服务认证是什么样的。您可以覆盖任何这些工厂并添加自定义逻辑,以从社交认证服务中注入Identity

但也许最好不要使用doctrine身份验证,而是将两种身份验证解决方案合并到一个自定义身份验证服务类中。那取决于你。

我将通过覆盖存储工厂类来举例说明在教条认证存储中为您的社交服务设置$identity。这将让您了解如何使用这些东西。

在您的应用程序module.config.php中使用自定义工厂类覆盖存储工厂的密钥(确保在doctrine模块之后加载模块,以便在配置合并时覆盖密钥):

'doctrine' => array(
    'doctrine_factories' => array(
        'authenticationstorage' => 'Application\Service\Authentication\CustomStorageFactory',
    )
)

现在在应用程序文件夹中创建此自定义类。您的CustomStorageFactory可能就像这样:

<?php

namespace Application\Service\Authentication;

use DoctrineModule\Authentication\Storage\ObjectRepository;
use Zend\ServiceManager\ServiceLocatorInterface;
use DoctrineModule\Service\Authentication\StorageFactory;

/**
 * Customized factory to inject identity from social authentication
 */
class CustomStorageFactory extends StorageFactory
{
    /**
     * @param \Zend\ServiceManager\ServiceLocatorInterface $serviceLocator
     * @return \Zend\Authentication\AuthenticationService
     */
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        // Construct storage like normally by calling parent class
        $doctrineStorage = parent::__construct($serviceLocator);

        // Write the identity into the storage
        $socialService = $serviceLocator->get('SocialAuthenticationService');
        if($socialService->hasIdentity()){
            $identity = $socialService->getIdentity();
            $doctrineStorage->write($identity);
        }

        // return the storage
        return $doctrineStorage;
    }
}

现在你可以这样做:

$serviceLocator= $this->getServiceLocator();
$authService = $serviceLocator->get(`Zend\Authentication\AuthenticationService`);

// Check if we have identity, if not we authenticate
if(!$authService->hasIdentity()){
    $authService->authenticate();
)
$authService->getIdentity();