FOSUserBundle - 首次登录后强制更改密码

dmr*_*rlc 5 php symfony fosuserbundle

在使用FOSUserBundle进行用户管理的Symfony2应用程序中,用户表已通过csv文件中的导入脚本和从数据组合生成的密码填充.

我想强制用户在首次登录时更改密码.

事件FOSUserEvents::SECURITY_IMPLICIT_LOGIN发生时,fos_user_change_password如果字段last_login为NULL ,则重定向到路由.

我的想法是重写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 );
    }
}
Run Code Online (Sandbox Code Playgroud)

我已经有一个包覆盖FOSUserBundle,它适用于控制器,表单等,但看起来它不是用eventListeners做的方式.

如何在首次登录后强制用户更改密码?

dmr*_*rlc 9

在@sjagr的宝贵提示的帮助下,关于fos_user.security.implicit_login这一点,fos_user.security.implicit_login以及关于在登录后立即执行操作的外部主题,我得到了一个有效的解决方案.

AGI\UserBundle \资源\设置\ 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 }
Run Code Online (Sandbox Code Playgroud)

AGI\UserBundle \事件监听\ 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 );
    }
}
Run Code Online (Sandbox Code Playgroud)

谢谢

  • 此解决方案在登录后立即强制用户访问"更改密码"页面,但如果用户只是忽略更改并导航到另一个页面,该怎么办? (10认同)