В моем приложении Symfony 3 я сделал так, что если пользователь неактивен в течение некоторого времени, он выходит из системы и снова запрашивает логин. Это делается с помощью следующего кода:
//RequestListener.php
public function onKernelRequest(GetResponseEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST != $event->getRequestType()) {
return;
}
if ($this->maxIdleTime > 0) {
$lapse = time() - $this->session->getMetadataBag()->getCreated();
$lapse_short = time() - $this->session->getMetadataBag()->getLastUsed();
if ($lapse >= $this->maxIdleTime || $lapse_short >= $this->shortIdleTime) {
$username = $this->securityToken->getToken()->getUser();
if ($username !== 'anon.'){
$this->session->invalidate();
$this->securityToken->setToken(null);
$event->setResponse(new RedirectResponse($this->router->generate('login')));
}
}
}
}
Но в этом случае перенаправление на регистрационную форму происходит, когда страница перезагружается. Я также хочу принудительно перенаправить на каждый вызов ajax. По умолчанию мои вызовы ajax обслуживаются следующим адресом: /ajax
Но когда срок действия сеанса истек, ajax "перенаправляется" на мой адрес страницы входа в систему и на вкладке "Сети браузера" я вижу следующее:
Моя функция ajax, которая должна перенаправляться, выглядит следующим образом:
function requestAjax(json_data, url) {
if(url.indexOf('login') !== -1){
window.location = './login';
}
var request = $.ajax({
url: root + '/' + url
, method: 'post'
, data: json_data
});
return request;
}
Но перенаправления не происходит. Итак, вопрос заключается в том, как принудительно перенаправлять на истекшие сеансы и вызовы ajax, а также почему статус ajax равен 200, но не сказать 302 в этом случае? Спасибо
UPD_1 Мой services.yml
для RequestListener.php
app.handler.session_idle:
class: AppBundle\EventListener\RequestListener
arguments: ["@session", "@security.token_storage", "@router", "@app.logger", "%session_lifetime%", "%session_active_lifetime%", "%instance_path%"]
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
Вы можете попробовать что-то вроде этого (протестировано и работает в Symfony 2.8)
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
class AjaxAuthenticationListener {
/*
* function onCoreException
* Check if session is expired and handles security related exceptions
* @param GetResponseForExceptionEvent $event An GetResponseForExceptionEvent instance
*
*/
public function onCoreException(GetResponseForExceptionEvent $event) {
$exception = $event->getException();
$event_request = $event->getRequest();
$session = $event->getRequest()->getSession();
if ($event_request->isXmlHttpRequest()) {
if ($exception instanceof AuthenticationException || $exception instanceof AccessDeniedException) {
$session->getFlashBag()->add('warning', 'You have been signed out automatically due to inactivity.');
$event->setResponse(new Response('Session expired', 403));
}
}
}
}
Как вы можете видеть, функция onCoreException возвращает код состояния 403.
Теперь, на домашней странице (в моем случае) или на странице, где вы будете иметь вызовы ajax, вы можете использовать "ajaxError" и поймать jqXHR.status, если это 403, затем перенаправить на страницу входа и использовать "FlashBag" для отображения сообщение, связанное с истекшим сеансом.
$(document).ready(function () {
//Catch AjaxAuthenticationListener response
$(document).ajaxError(function (event, jqXHR) {
if (403 === jqXHR.status) {
$(location).attr('href', '{{ path('login') }}');
}
});
Я пропустил объяснение, как функция onCoreException работает как служба и как она обрабатывает сеанс, когда он истек, принимая во внимание, что эта часть работает правильно в вашем коде.
services.yml:
app.gt.ajax.authentication.listener:
class: AppBundle\EventListener\AjaxAuthenticationListener
tags:
- { name: kernel.event_listener, event: kernel.exception, method: onCoreException, priority: 1000 }
Надеюсь, это полезно для вас.
onCoreException
в свойRequestListener.php
но он не срабатывает. Когда вызов ajax перенаправляется на вход в систему, он не воспринимает это как исключение или что-то подобное ((. Может быть, добавьте еще некоторые данные в моиservices.yml
? Я добавлю их в свой основной вопрос)