Php Symfony2 FOSbundle:记录每个用户的登录日期

Php Symfony2 FOSbundle:记录每个用户的登录日期,php,symfony,fosuserbundle,Php,Symfony,Fosuserbundle,如何在用户每次登录Symfony2时存储记录 我创建了UserLog实体,我想在其中记录记录的id、用户id和登录日期 我使用FOS用户包进行用户管理。我看到了只记录每个用户最后一次登录的问题,但不知道如何记录每个登录日期,您需要覆盖默认的身份验证处理程序并在那里进行登录 您需要为新的身份验证处理程序创建服务: services.yml: parameters: fos_user_security.component.authentication.handler.login_su

如何在用户每次登录Symfony2时存储记录

我创建了UserLog实体,我想在其中记录记录的id、用户id和登录日期


我使用FOS用户包进行用户管理。我看到了只记录每个用户最后一次登录的问题,但不知道如何记录每个登录日期,您需要覆盖默认的身份验证处理程序并在那里进行登录

您需要为新的身份验证处理程序创建服务: services.yml:

    parameters:
    fos_user_security.component.authentication.handler.login_success_handler.class: Path\To\New\Handler



    services:
fos_user_security.component.authentication.handler.login_success_handler:
             class:  %fos_user_security.component.authentication.handler.login_success_handler.class%
             arguments:  [@router, @security.context]
             tags:
                 - { name: 'monolog.logger', channel: 'security' }
创建处理程序并执行以下逻辑: 名称空间应用程序\Sonata\UserBundle\Services

use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Router;

class LoginSuccessHandler implements AuthenticationSuccessHandlerInterface
{

    protected $router;
    protected $security;

    public function __construct(Router $router, SecurityContext $security)
    {
        $this->router = $router;
        $this->security = $security;
    }

    public function onAuthenticationSuccess(Request $request, TokenInterface $token)
    {

        if ($this->security->isGranted('ROLE_USER'))

        // create your new entity and add the data you need

        }

        return $response;
    }
在security.yml中,您需要定义新的success_处理程序,如下所示:

main:
    pattern:             ^/
    context:             user
    form_login:
        provider:       fos_userbundle
        csrf_provider: form.csrf_provider
        login_path:     /login
        #use_forward:    false
        check_path:     fos_user_security_check
        success_handler: fos_user_security.component.authentication.handler.login_success_handler // the handler
        #failure_path:   null
        always_use_default_target_path: false
        default_target_path: profile
您必须实现一个AuthenticationHandler,用于侦听onAuthenticationSuccess事件

首先,使用getter和setter在用户实体datetime中创建lastLogin字段,可以为null

然后,创建如下内容:

<?php

namespace Acme\TestBundle\Handler;

use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\DependencyInjection\ContainerAware;

class AuthenticationHandler extends ContainerAware implements AuthenticationSuccessHandlerInterface
{
    function onAuthenticationSuccess(Request $request, TokenInterface $token)
    {
        $user = $token->getUser();
        $lastLogin = new \DateTime();

        $user->setLastLogin($lastLogin);
        $this->container->get('doctrine')->getEntityManager()->flush();

        // redirect the user for example
        return new RedirectResponse($this->container->get('router')->generate('login_success'));
    }
}
并将其配置为身份验证成功\u处理程序:

希望这对你有帮助

编辑

我错了,谢谢@JasonRoman

创建包含日期属性的实体(如LoginRecord),而不是lastLogin属性

/**
 * LoginRecord.
 *
 * @ORM\Entity
 * @ORM\Table(name="user_logins")
 */
class LoginRecord
{
    // Identifier

    /** @ORM\Column(name="date", type="date") */
    protected $date;

    /**
     * @ORM\ManyToOne(targetEntity="\Acme\TestBundle\Entity\User", inversedBy="loginRecords")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false)
     */
    protected $user;

    public function setDate($date)
    {
        $this->date = $date;

        return $date;
    }

    public function getDate()
    {
        return $this->date;
    }

    public function setUser(User $user)
    {
        $this->user = $user;

        return $this;
    }

    public function getUser()
    {
        return $this->user;
    }

}
然后,在用户实体中添加一个名为$loginRecords的属性,该属性表示与LoginRecord的一对多关联,即targetClass

并且,不要使用setLastLogin,而是使用addLoginRecord$date在AuthenticationHandler中记录用户登录:

下面是Symfony4.2的解决方案

根据需要,必须侦听security.interactive\u登录事件并创建LoginListener

代码1

代码2

必须调整此示例以满足定制需求


例如LoginListener进入

您发布的问题中选择的答案包含您所需的一切。你尝试了什么,出了什么问题?谢谢你的解决方案。我完全按照您写的那样做了,但出现了以下错误:service security.firewall.map.context.main依赖于不存在的service fos\u user\u security.component.authentication.handler.login\u success\u处理程序。你认为会有什么问题?可能会有几个问题。您使用的是哪个Symfony版本?Symfony版本2.7.3只记录用户的最后一次登录-他希望它记录用户登录的每个日期。@chalasr我已经尝试了您的解决方案。我没有记录上次登录,而是尝试记录每次登录:$user=$token->getUser$登录\日期=新建\日期时间$用户日志=新用户日志$用户日志->设置用户$user$用户日志->设置登录日期$login\u日期$这个->容器->获取“条令”->getEntityManager->刷新;返回新的重定向响应$this->container->get'router'->generate'profile',array'user'=>$user->getUsername;它不起作用。我的意思是我已正确登录并重定向,但数据未被记录。请参阅我的示例。用户实体中的$loginRecords和addLoginRecord中的setUser$this中肯定缺少cascade={persist}。也不要忘记构造函数。
// app/config/security.yml
# ...
form_login:
    # ...
    success_handler: authentication_handler
/**
 * LoginRecord.
 *
 * @ORM\Entity
 * @ORM\Table(name="user_logins")
 */
class LoginRecord
{
    // Identifier

    /** @ORM\Column(name="date", type="date") */
    protected $date;

    /**
     * @ORM\ManyToOne(targetEntity="\Acme\TestBundle\Entity\User", inversedBy="loginRecords")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false)
     */
    protected $user;

    public function setDate($date)
    {
        $this->date = $date;

        return $date;
    }

    public function getDate()
    {
        return $this->date;
    }

    public function setUser(User $user)
    {
        $this->user = $user;

        return $this;
    }

    public function getUser()
    {
        return $this->user;
    }

}
// User entity

class User
{
    // ... Your other properties

    /** @ORM\OneToMany(targetEntity="\Acme\TestBundle\Entity\LoginRecord", mappedBy="user", cascade={"persist", "remove"}) */
    protected $loginRecords;

    public function __construct()
    {
        // ...
        $this->loginRecords = new \Doctrine\Common\Collections\ArrayCollection();
    }

    public function addLoginRecord(LoginRecord $loginRecord)
    {
        $this->loginRecords[] = $loginRecord;
        $loginRecord->setUser($this);

        return $this;
    }

    public function removeLoginRecord(LoginRecord $loginRecord)
    {
        $this->loginRecords->removeElement($loginRecord);
    }


    public function getLoginRecords()
    {
        return $this->loginRecords;
    }
}
function onAuthenticationSuccess(Request $request, TokenInterface $token)
{
    $user = $token->getUser();
    $lastLogin = new \DateTime();

    $record = new LoginRecord();
    $record->setDate($lastLogin);

    $user->addLoginRecord($record);
    $this->container->get('doctrine')->getEntityManager()->flush();

    // redirect the user for example
    return new RedirectResponse($this->container->get('router')->generate('login_success'));
}
app.login_listener:
    class: App\EventListener\LoginListener
    tags:
        - { name: 'kernel.event_listener', event: 'security.interactive_login' }
// src/EventListener/LoginListener.php

namespace App\EventListener;

use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;

class LoginListener
{
    private $em;

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

    public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
    {
        // Get the User entity.
        $user = $event->getAuthenticationToken()->getUser();

        // Update your field here.
        $user->setLastLogin(new \DateTime());

        // Persist the data to database.
        $this->em->persist($user);
        $this->em->flush();
    }
}