Symfony 3 ajax redirect, если сессия истекла

1

В моем приложении 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 "перенаправляется" на мой адрес страницы входа в систему и на вкладке "Сети браузера" я вижу следующее:

Изображение 174551

Моя функция 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 }
Теги:

1 ответ

0

Вы можете попробовать что-то вроде этого (протестировано и работает в 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 }

Надеюсь, это полезно для вас.

  • 0
    Я добавил ваш код onCoreException в свой RequestListener.php но он не срабатывает. Когда вызов ajax перенаправляется на вход в систему, он не воспринимает это как исключение или что-то подобное ((. Может быть, добавьте еще некоторые данные в мои services.yml ? Я добавлю их в свой основной вопрос)
  • 0
    @ Маша, я обновил свой ответ и добавил конфигурацию service.yml.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню