每次用户登录Symfony2时如何存储记录?
我创建了UserLog实体,我想记录记录的id,用户的id和登录日期。
我正在使用FOS用户包进行用户管理。我看到只记录每个用户Symfony2 Login and Security的最后一次登录的问题,但是无法弄清楚如何记录每个登录日期
答案 0 :(得分:0)
您需要覆盖默认的身份验证处理程序并在那里登录。
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' }
命名空间Application \ 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_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
答案 1 :(得分:0)
您必须实施一个AuthenticationHandler
来监听onAuthenticationSuccess
事件。
首先,使用getter和setter在用户实体(datetime,nullable)中创建lastLogin
字段。
然后,创建如下:
<?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。
创建一个包含lastLogin
属性的LoginRecord
等实体,而不是date
属性。
/**
* 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
的{{1}}的一对多关联。
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
答案 2 :(得分:0)
这是Symfony4.2的解决方案
根据Symfony documentation,必须收听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