[英]FOSUserBundle - Force password change after first login
在使用 FOSUserBundle 进行用户管理的 Symfony2 应用程序中,用户表已通过从 csv 文件的导入脚本和从数据组合生成的密码进行填充。
我想强制用户在第一次登录时更改他的密码。
当事件FOSUserEvents::SECURITY_IMPLICIT_LOGIN
发生时,如果字段last_login
为 NULL,则重定向到路由fos_user_change_password
。
我的想法是像这样重写AGI\\UserBundle\\EventListener\\LastLoginListener
类的onImplicitLogin(UserEvent $event)
,但该类没有被覆盖:
public function onImplicitLogin(UserEvent $event) {
$user = $event->getUser ();
if ($user->getLastLogin () === null) {
$user->setLastLogin ( new \DateTime () );
$this->userManager->updateUser ( $user );
$response = new RedirectResponse ( $this->router->generate ( 'fos_user_change_password' ) );
$this->session->getFlashBag ()->add ( 'notice', 'Please change your password' );
$event->setResponse ( $response );
}
}
我已经有一个覆盖 FOSUserBundle 的包,它适用于控制器、表单等,但看起来它不是使用 eventListeners 的方法。
如何强制用户在第一次登录后更改密码?
在@sjagr 关于fos_user.security.implicit_login
的宝贵提示的帮助下,我找到了fos_user.security.implicit_login
和一个关于登录后立即做事的外部主题,我得到了一个fos_user.security.implicit_login
解决方案。
AGI\\UserBundle\\Resources\\config\\services.yml
login_listener:
class: 'AGI\UserBundle\EventListener\LoginListener'
arguments: ['@security.context', '@router', '@event_dispatcher']
tags:
- { name: 'kernel.event_listener', event: 'security.interactive_login', method: onSecurityInteractiveLogin }
AGI\\UserBundle\\EventListener\\LoginListener.php
<?php
namespace AGI\UserBundle\EventListener;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Bundle\FrameworkBundle\Routing\Router;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class LoginListener {
private $securityContext;
private $router;
private $dispatcher;
public function __construct(SecurityContext $securityContext, Router $router, EventDispatcherInterface $dispatcher) {
$this->securityContext = $securityContext;
$this->router = $router;
$this->dispatcher = $dispatcher;
}
public function onSecurityInteractiveLogin(InteractiveLoginEvent $event) {
if ($this->securityContext->isGranted ( 'IS_AUTHENTICATED_FULLY' )) {
$user = $event->getAuthenticationToken ()->getUser ();
if ($user->getLastLogin () === null) {
$this->dispatcher->addListener ( KernelEvents::RESPONSE, array (
$this,
'onKernelResponse'
) );
}
}
}
public function onKernelResponse(FilterResponseEvent $event) {
$response = new RedirectResponse ( $this->router->generate ( 'fos_user_change_password' ) );
$event->setResponse ( $response );
}
}
谢谢
如果由于某些业务规则需要用户更改密码,可以使用内核请求 EventListener:
<?php
namespace App\EventListener;
use App\Model\UserInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class ChangePasswordListener
{
private TokenStorageInterface $security;
private RouterInterface $router;
private array $excludedRoutes = [
'admin_change_password',
'admin_login',
'admin_login_check',
'admin_logout',
];
public function __construct(
TokenStorageInterface $security,
RouterInterface $router
) {
$this->security = $security;
$this->router = $router;
}
public function onKernelRequest(RequestEvent $event): void
{
if (false === $event->isMasterRequest()) {
return;
}
if ($event->getRequest()->isXmlHttpRequest()) {
return;
}
$currentRoute = $event->getRequest()->get('_route');
if (\in_array($currentRoute, $this->excludedRoutes, true)) {
return;
}
$token = $this->security->getToken();
if (null === $token) {
return;
}
$user = $token->getUser();
if ($user instanceof UserInterface && $user->shouldPasswordChange()) {
$response = new RedirectResponse($this->router->generate('admin_security_profile_change_password'));
$event->setResponse($response);
}
}
}
服务.yaml:
services:
App\EventListener\ChangePasswordListener:
arguments:
- '@security.token_storage'
- '@router'
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: -100 }
您还应该提供自己的 UserInterface 方法“shouldPasswordChange”和它的自定义实现。
它适用于 Symfony 5.0 和 PHP 7.4,但如果您修改此代码,它也适用于较低的 PHP 版本。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.