我正在研究基于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_LOGIN
和AuthenticationEvents::AUTHENTICATION_SUCCESS
都被触发(顺便说一句:两者之间有什么区别)?
但是,如果用户已登录并访问页面,则不会触发这两个事件。
当会话过期且remember_me
cookie没有时,这是一个问题。我在浏览器中刷新页面后几天没有使用该机器时遇到的问题:remember_me
cookie仍处于活动状态,因此用户仍然登录。但是页面是使用默认语言刷新的,而不是用户语言,只有在会话过期时才有可能...
我没有在配置文件中配置会话生存时间,Symfony调试工具栏显示会话生命周期为0.当然,我可以延长生命周期并使其长于remember_me选项的生命周期。但是,每次用户进行身份验证时,从用户设置重新读取区域设置将是一个更清晰的解决方案。
我假设认证是在每个请求上完成的。通过登录表单(=交互式登录)提交的用户凭据或存储在remember_me
cookie中的信息。这不正确吗?
在这种情况下,我希望,每次请求都会触发AuthenticationEvents::AUTHENTICATION_SUCCESS
事件。但事实似乎并非如此。
长话短说:
如何确保用户登录时使用用户设置中的区域设置?
根据我的经验,每次我们发出请求(如果基于会话的身份验证)symfony检查请求是否匹配任何活动会话(使用某个cookie作为会话标识符或类似的东西)。如果是,则触发onAuthenticationSuccess
,否则您将被重定向到登录页面。提交登录表单后,如果用户凭据有效,则会对您进行身份验证并触发onSecurityInteractiveLogin
。
因此,如果凭证在每个请求中都有效,则onAuthenticationSuccess
会触发,而onSecurityInteractiveLogin
仅在成功登录时触发提交。在任何情况下,经过成功验证后,您将在整个内核事件中转发到目标URL,从onKernelRequest
事件开始。
所以,我认为问题可能是,当成功的onAuthenticationSuccess
发生时,你实际上将用户语言填充到会话中,但在那之后onKernelRequest
被触发并且你用这个覆盖了那个信息
$request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
如果这是问题,请考虑在onSecurityInteractiveLogin
事件中设置语言