如何在Symfony中记住登录时设置用户区域设置?

问题描述 投票:0回答:1

我正在研究基于Symfony 2.8的项目。该网页可以使用不同的语言,所选语言存储在Session中。使用Locale Listener类,当用户进入页面或登录时设置正确的语言环境没有问题:

class LocaleListener implements EventSubscriberInterface {
    private $defaultLocale;

    public function __construct($defaultLocale = 'de') {
        $this->defaultLocale = $defaultLocale;
    }

    public static function getSubscribedEvents() {
        return array(
            // must be registered before the default Locale listener
            KernelEvents::REQUEST => array(array('onKernelRequest', 17)),
            SecurityEvents::INTERACTIVE_LOGIN => array(array('onSecurityInteractiveLogin', 18)),                
            AuthenticationEvents::AUTHENTICATION_SUCCESS => 'onAuthenticationSuccess',
        );
    }

    public function onKernelRequest(GetResponseEvent $event) {
        $request = $event->getRequest();

        if (!$request->hasPreviousSession()) 
            return;

        if ($locale = $request->attributes->get('_locale')) {            
            // try to see if the locale has been set as a _locale routing parameter    
            $request->getSession()->set('_locale', $locale);
        } else {
            // if no explicit locale has been set on this request, use one from the session            
            $request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
        }
    }

    public function onSecurityInteractiveLogin(InteractiveLoginEvent $event) {
        // ...get locale from user settings and it info to session...
    }

    public function onAuthenticationSuccess(AuthenticationEvent $event) {
        // ...get locale from user settings and it info to session...
    }
}

这与使用登录侦听器扩展的Symfony docs中的代码相同。当用户主动登录时,它工作得很好。在这种情况下,SecurityEvents::INTERACTIVE_LOGINAuthenticationEvents::AUTHENTICATION_SUCCESS都被触发(顺便说一句:两者之间有什么区别)?

但是,如果用户已登录并访问页面,则不会触发这两个事件。

当会话过期且remember_me cookie没有时,这是一个问题。我在浏览器中刷新页面后几天没有使用该机器时遇到的问题:remember_me cookie仍处于活动状态,因此用户仍然登录。但是页面是使用默认语言刷新的,而不是用户语言,只有在会话过期时才有可能...

我没有在配置文件中配置会话生存时间,Symfony调试工具栏显示会话生命周期为0.当然,我可以延长生命周期并使其长于remember_me选项的生命周期。但是,每次用户进行身份验证时,从用户设置重新读取区域设置将是一个更清晰的解决方案。

我假设认证是在每个请求上完成的。通过登录表单(=交互式登录)提交的用户凭据或存储在remember_me cookie中的信息。这不正确吗?

在这种情况下,我希望,每次请求都会触发AuthenticationEvents::AUTHENTICATION_SUCCESS事件。但事实似乎并非如此。

长话短说:

如何确保用户登录时使用用户设置中的区域设置?

php symfony session authentication local
1个回答
0
投票

根据我的经验,每次我们发出请求(如果基于会话的身份验证)symfony检查请求是否匹配任何活动会话(使用某个cookie作为会话标识符或类似的东西)。如果是,则触发onAuthenticationSuccess,否则您将被重定向到登录页面。提交登录表单后,如果用户凭据有效,则会对您进行身份验证并触发onSecurityInteractiveLogin

因此,如果凭证在每个请求中都有效,则onAuthenticationSuccess会触发,而onSecurityInteractiveLogin仅在成功登录时触发提交。在任何情况下,经过成功验证后,您将在整个内核事件中转发到目标URL,从onKernelRequest事件开始。

所以,我认为问题可能是,当成功的onAuthenticationSuccess发生时,你实际上将用户语言填充到会话中,但在那之后onKernelRequest被触发并且你用这个覆盖了那个信息

$request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));

如果这是问题,请考虑在onSecurityInteractiveLogin事件中设置语言

© www.soinside.com 2019 - 2024. All rights reserved.