在使用FOSUserBundle进行用户管理的Symfony2应用程序中,用户表已通过csv文件中的导入脚本和从数据组合生成的密码填充。
我想强制用户在首次登录时更改密码。
当事件FOSUserEvents::SECURITY_IMPLICIT_LOGIN
发生时,如果字段fos_user_change_password
为NULL,则重定向到路由last_login
。
我的想法是重写类onImplicitLogin(UserEvent $event)
的方法AGI\UserBundle\EventListener\LastLoginListener
,但这个类没有被覆盖:
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的方法。
首次登录后如何强制用户更改密码?
答案 0 :(得分:9)
借助@sjagr关于驱使我fos_user.security.implicit_login
的{{1}}以及关于doing stuff right after login的外部主题的宝贵提示,我得到了一个有效的解决方案。
AGI \ UserBundle \资源\配置\ services.yml
fos_user.security.implicit_login
AGI \ UserBundle \事件监听\ LoginListener.php
login_listener:
class: 'AGI\UserBundle\EventListener\LoginListener'
arguments: ['@security.context', '@router', '@event_dispatcher']
tags:
- { name: 'kernel.event_listener', event: 'security.interactive_login', method: onSecurityInteractiveLogin }
谢谢
答案 1 :(得分:0)
如果由于某些业务规则要求用户更改密码,则可以使用内核请求EventListener:
VM
Child1
Action11
Action12
Child2
Action21
Action22
Collection
Item1
ElementAction
Item2
ElementAction
Item3
ElementAction
...
services.yaml:
<?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);
}
}
}
您还应该为自己的UserInterface提供方法“ shouldPasswordChange”和自定义实现。
它在Symfony 5.0和PHP 7.4上很好用,但是如果您修改此代码,它也应在较低的PHP版本上使用。