ZF2/doctrine ORM认证不同的Entity
ZF2 / doctrine ORM authentication different Entity
在我的应用程序 (ZF2/ORM) 中,我有 3 个实体(具有单一 Table 继承)
User
Owner extends User
Agent extends User
我想为 3 个实体使用
doctrine.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);
},
),
),
以及登录的过程
//LoginController.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
}
如何在不关心对象类型的情况下执行此过程,
当我尝试使用代理的电子邮件登录时,出现此错误
Catchable fatal error: Argument 1 passed to Application\Module::{closure}() must be an instance of User, instance of Application\Entity\Owner given
您提到的错误是由于类型提示:
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' 实际上执行上述操作(但使用事件管理器),因此即使您不使用它也可能值得一看。
在我的应用程序 (ZF2/ORM) 中,我有 3 个实体(具有单一 Table 继承)
User
Owner extends User
Agent extends User
我想为 3 个实体使用 doctrine.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);
},
),
),
以及登录的过程
//LoginController.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
}
如何在不关心对象类型的情况下执行此过程, 当我尝试使用代理的电子邮件登录时,出现此错误
Catchable fatal error: Argument 1 passed to Application\Module::{closure}() must be an instance of User, instance of Application\Entity\Owner given
您提到的错误是由于类型提示:
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' 实际上执行上述操作(但使用事件管理器),因此即使您不使用它也可能值得一看。