如何
存储用户每次登录Symfony2时的记录?
我创建了用户日志实体,我想在其中记录记录 ID、用户 ID 和登录日期。
我正在使用 FOS 用户捆绑包进行用户管理。我看到了只记录每个用户Symfony2登录和安全的最后一次登录的问题,但无法弄清楚如何记录每个登录日期
这是Symfony4.2的解决方案
根据Symfony文档,必须收听security.interactive_login
事件并创建LoginListener
。
代码 1
app.login_listener:
class: App'EventListener'LoginListener
tags:
- { name: 'kernel.event_listener', event: 'security.interactive_login' }
代码 2
// 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();
}
}
必须调整此示例以满足自定义需求。
例如,LoginListener
归功于Rihards Steinbergs
您必须实现一个侦听onAuthenticationSuccess
事件的AuthenticationHandler
。
首先,在用户实体(日期时间、可为空)中创建 lastLogin
字段,其中包含 getter 和 setter。
然后,创建如下:
<?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'));
}
}
将其注册为服务:
// app/config/services.yml
services:
authentication_handler:
class: Acme'TestBundle'Handler'AuthenticationHandler
calls:
- [ setContainer, [ @service_container ] ]
并将其配置为身份验证success_handler
:
// app/config/security.yml
# ...
form_login:
# ...
success_handler: authentication_handler
希望这对你有帮助。
编辑
我的错误,谢谢@JasonRoman。
创建一个包含date
属性的实体(如 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
。
// 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;
}
}
并且,不要使用 setLastLogin
,请使用 addLoginRecord($date)
将用户登录记录在AuthenticationHandler
中:
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'));
}
您需要覆盖默认的身份验证处理程序并在那里进行登录。
- 您需要为新的身份验证处理程序创建一个服务:
服务.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' }
- 创建处理程序并执行逻辑:
奏鸣曲''用户捆绑包''服务;
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_handler,如下所示:
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