我已经跟随guide实施身份验证/授权,我可以登录。
我从指南中的内容中得到了一个主要区别。我没有isActive
属性,而是在我的数据库中有一个状态表。
我不知道如何根据状态表中的值而不是指南中引用的isActive
属性来拒绝/接受登录。
我不确定要发布什么代码,因为它的工作原理与指南相同,我非常确定Symfony安全系统会处理我无法看到的所有身份验证内容。
即使你只是指出我正确的方向,我将不胜感激。
修改
使用ChadSikorra的建议我想出了这段代码来实现AdvancedUserInterface函数:
public function isAccountNonExpired()
{
$status = $this->getTblStatus()->getStatustext();
switch ($status){
case "expired":
return false;
default:
return true;
}
}
public function isAccountNonLocked()
{
$status = $this->getTblStatus()->getStatustext();
switch ($status){
case "locked":
return false;
case "suspended":
return false;
case "registered":
return false;
default:
return true;
}
}
public function isCredentialsNonExpired()
{
return $this->pwdexpired;
}
public function isEnabled()
{
$status = $this->getTblStatus()->getStatustext();
if($status != 'active')
return false
else
return true;
}
我接下来的问题是如何处理用户具有其中一种状态时引发的异常?
根据我到目前为止的情况,我认为通过捕获loginAction中的错误是可行的。我不知道该怎么做就是找出错误,但我会继续挖掘。
/**
* @Route("/Login", name="wx_exchange_login")
* @Template("WXExchangeBundle:User:login.html.twig")
* User login - Open to public
* Authenticates users to the system
*/
public function loginAction(Request $request)
{
$session = $request->getSession();
if ($this->get('security.context')->isGranted('IS_AUTHENTICATED_REMEMBERED'))
{
// redirect authenticated users to homepage
return $this->redirect($this->generateUrl('wx_exchange_default_index'));
}
// get the login error if there is one
if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$error = $request->attributes->get(
SecurityContext::AUTHENTICATION_ERROR
);
} else {
$error = $session->get(SecurityContext::AUTHENTICATION_ERROR);
$session->remove(SecurityContext::AUTHENTICATION_ERROR);
}
if($error instanceof LockedException)
{
}
return $this->render(
'WXExchangeBundle:User:login.html.twig',
array(
// last username entered by the user
'last_username' => $session->get(SecurityContext::LAST_USERNAME),
'error' => $error,
)
);
}
我现在能够检查Exception的类型,但我不知道如何获取特定状态,以便我可以重定向到正确的位置。这是这个难题的最后一部分。
答案 0 :(得分:3)
您可以在用户实体上添加映射到自定义状态表,如下所示:
/**
* @ORM\OneToOne(targetEntity="AccountStatus")
* @ORM\JoinColumn(name="status_id", referencedColumnName="id", nullable=true)
*/
private $accountStatus;
这还需要创建一个描述自定义状态表的实体。然后,您可以通过实现您链接的指南中引用的Symfony\Component\Security\Core\User\AdvancedUserInterface
在您的用户实体中使用此映射。然后实现类似这样的isEnabled
函数......
public function isEnabled()
{
return $this->getAccountStatus()->getIsActive(); /* Or whatever you named it */
}
修改强>
基于AdvancedUserInterface
的{{3}},如果您想要使用自定义逻辑来处理不同的状态,则需要注册异常监听器......
如果您需要为任何这些情况执行自定义逻辑,那么 你需要注册一个异常监听器并注意 每种情况下抛出的特定异常实例。所有例外都是 AccountStatusException的子类
有一篇非常好的Cookbook文章用于创建类似API Doc的内容。此实例中的基本过程是为侦听器创建类...
的src / Acme公司/ DemoBundle /事件监听/ AcmeExceptionListener.php
namespace Acme\DemoBundle\EventListener;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Exception\DisabledException;
use Symfony\Component\Security\Core\Exception\LockedException;
class AcmeExceptionListener
{
public function onKernelException(GetResponseForExceptionEvent $event)
{
$exception = $event->getException();
if ($exception instanceof DisabledException) {
// Customize your response object to display the exception details
$response = new Response();
$response->setContent('<html><body><h1>Custom disabled page!</h1></body></html>');
// Send the modified response object to the event
$event->setResponse($response);
}
elseif ($exception instanceof LockedException) {
// Or render a custom template as a subrequest instead...
$kernel = $event->getKernel();
$response = $kernel->forward('AcmeDemoBundle:AccountStatus:locked', array(
'exception' => $exception,
));
$event->setResponse($response);
}
// ... and so on
}
}
以上只是基本的例子,但它无论如何都会给你一个要点。从技术上讲,我猜你也可以通过扩展AccountStatusException
来制作自定义异常,然后将它们放入你的AdvancedUserInterface
实现的逻辑中。然后你会确切地知道你正在捕捉的状态。无论如何,请确保将监听器注册为服务。
应用程序/配置/ config.yml
services:
kernel.listener.your_listener_name:
class: Acme\DemoBundle\EventListener\AcmeExceptionListener
tags:
- { name: kernel.event_listener, event: kernel.exception, method: onKernelException }
另一种方法是实现某种自定义用户检查器。请参阅此问题:here