UserChecker-使用实体管理器

时间:2018-08-21 09:31:42

标签: symfony symfony-3.4 symfony-security

我的网站正在运行Symfony 3.4,并且我创建了自己的用户成员系统。 我的用户实体包含一个Datetime字段“ lastLogin”,每次用户登录时我都找不到解决方案来更新它。

我创建了一个自定义UserChecker,然后尝试更新其中的字段:

<?php

namespace CoreBundle\Security;

use CoreBundle\Entity\User as AppUser;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;

class UserChecker implements UserCheckerInterface
{
    public function checkPreAuth(UserInterface $user)
    {
        if (!$user instanceof AppUser) {
            return;
        }
        if ( $user->getDeleted() || !$user->getEnabled()  )
        {
            throw new AuthenticationException();
        }
        else
        {
            // BELOW IS WHAT I TRY, BUT FAIL.
            $entityManager = $this->get('doctrine')->getManager();
            $user->setLastLogin(new \DateTime());
            $entityManager->persist($user);
            $entityManager->flush();
        }
    }

    public function checkPostAuth(UserInterface $user)
    {
        if (!$user instanceof AppUser) {
            return;
        }
    }
}

但是它不起作用。也许我不能在该文件中使用理论实体管理器?

如果我使用$this->get('doctrine')->getManager();,我会得到:

  

致命错误:调用未定义的方法   CoreBundle \ Security \ UserChecker :: get()

2 个答案:

答案 0 :(得分:3)

Dunno为什么@doncallisto删除了他的帖子。 (恕我直言)是对的。

看看http://symfony.com/doc/current/components/security/authentication.html#authentication-success-and-failure-events

所以您有几种选择。

  • SecurityEvents::INTERACTIVE_LOGIN-每次用户触发 填写登录表单并提交凭据。会工作,但是你 如果您有remember_me cookie或类似的

  • ,将不会获得last_login更新
  • AuthenticationEvents::AUTHENTICATION_SUCCESS-每次触发 (每个请求)验证成功时。这意味着您的last_login将在每次每次请求时每次更新,除非用户退出退出

所以您需要一个EventSubscriber。看一下这篇文章。 https://thisdata.com/blog/subscribing-to-symfonys-security-events/

也许您需要一个简化的版本。

public static function getSubscribedEvents()
{
        return array(
            // AuthenticationEvents::AUTHENTICATION_FAILURE => 'onAuthenticationFailure', // no need for this at that moment
            SecurityEvents::INTERACTIVE_LOGIN => 'onSecurityInteractiveLogin', // this ist what you want
        );
}

,然后是onSecurityInteractiveLogin方法本身。

public function onSecurityInteractiveLogin( InteractiveLoginEvent $event )
{
    $user = $this->tokenStorage->getToken()->getUser();
    if( $user instanceof User )
    {
      $user->setLastLogin( new \DateTime() );
      $this->entityManager->flush();
    }
}

P.S。 FosUserBundle使用Interactive_login和一个自定义事件在实体上设置last_login 看一下:https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/EventListener/LastLoginListener.php#L63

答案 1 :(得分:0)

朋友,您可以使用它来通过构造函数注入entityManager

const [time, setTime] = useState(10);

// somewhere else
setTime(time => time - 1)

然后在checkPreAuth中调用它

use Doctrine\ORM\EntityManagerInterface;

public function __construct(EntityManagerInterface $userManager){
    $this->userManager = $userManager;
}