Как я могу остановить вызов AJAX, сохранив сессию PHP - PullRequest
4 голосов
/ 20 июля 2011

У меня на сайте установлена ​​система аутентификации с использованием CakePHP. Для этого он использует PHP-сессии.

То, что я имею в виду, это AJAX-вызов (в пределах setInterval, работающего каждую минуту) функции, которая проверяет, вошел ли пользователь в систему. Если он возвращает false, тогда Javascript берет текущий URL и пытается перенаправить их , который, в свою очередь, перенаправляет их на страницу входа. Теоретически это работает, потому что он активно просит пользователя повторно войти в систему вместо того, чтобы проводить устаревшую сессию, которая просто попросит его войти в систему, как только они что-то нажмут. Моя проблема в том, что мой вызов AJAX поддерживает сеанс. Так что никогда не выходите из системы (чего мы не хотим)

Есть ли что-нибудь, что я могу сделать в CakePHP или любых других методах, которые я могу использовать, чтобы остановить это?

Ответы [ 7 ]

2 голосов
/ 17 сентября 2011

Добавьте &ajax= (что угодно) в строку запроса при проверке действительности сеанса.

Затем измените код сеанса PHP:

session_start();
if(!isset($_GET["ajax"])) $_SESSION["lastactivity"] = time();
if(now() - $_SESSION["lastactivity"] > 3600){ //3600 seconds
    header("Location: login.php?url="+urlencode(str_replace("&ajax=", "", $_SERVER["REQUEST_URI"])));
    //Example:
    // Location: login.php?url=/sensible/secret.php?mode=show&hide=nothing
    exit;
}
0 голосов
/ 20 августа 2015

Здесь я нашел решение для определения, был ли сеанс живым или нет.

Нет необходимости в накладных расходах .. Мы можем обнаружить и перенаправить тайм-аут сеанса по обычным http-запросам. Где, как в ajax, мы должны относиться к этому по-другому, с некоторой логикой.

# шаг 1 (на стороне сервера)

На стороне php. Сначала создайте функцию аутентификации, которая должна вызывать эту аутентификацию в первой строке всей страницы.

Лучше всего добавить эту функцию auth () в файл config.php или файл auth.php и включить во все файлы php после создания сеанса.

include 'config / auth.php';

// in auth.php file copy and past the following lines 

      function auth() {
        if (!isset($_SESSION['USER_ID'])) {
        //  checking whether the request is ajax or not. Ajax requests are xml http request 
            if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
               // set a status code manually. 418 is unused http code
                header("HTTP/1.0 418 Session Timeout", TRUE);
               //  return or send a json response with status string and location to redirect
                echo json_encode(array(
                    "status" => "time_out",
                    "location" => BASE_URL . "login.php?message=Session Timeout! Please log in and Try again.",
                ));
                exit;
            }
       // whether the request is normal http request do the redirection from the server side
            if (basename($_SERVER['PHP_SELF']) != 'login.php') {
                header("Location:" . BASE_URL . "login.php");
            }
        } }

# шаг 2 (на стороне клиента)

Здесь я использую jQuery создайте файл js, который должен вызывать все html (шаблоны) страницы в проекте.

Лучше всего включать в верхний или нижний колонтитул commen

создать настройки ajax

$.ajaxSetup({
    statusCode: {
        418: function (respose) {
            // $.parseJSON() can avoid by specifying dataType:"json" in ajax parameters
            var jsonObject = $.parseJSON(respose.responseText);
            if (jsonObject.status == "time_out") {
                window.location = jsonObject.location;
            }
        }
    }
});

Хорошего дня ...

0 голосов
/ 26 февраля 2013

Это не совсем отвечает на вопрос, который вы задаете, но я считаю это лучшей практикой, которой я поделился.

setInterval () на самом деле не ведет себя так, как вы ожидаете. Это не означает, что ваш код будет выполняться каждую минуту, это только гарантирует, что ваш код будет добавляться в очередь каждую минуту.

Проблема в том, что код таймера может не завершить выполнение перед добавлением кода в очередь снова . Результатом будет то, что код таймера запускается несколько раз подряд без количества времени между ними. К счастью, движки JavaScript достаточно умны, чтобы избежать этой проблемы. При использовании setInterval () код таймера добавляется в очередь, только если нет других экземпляров кода таймера уже в очереди. Это гарантирует, что время между добавлениями код таймера для очереди - это, как минимум, указанный интервал.

Недостаток этого правила для повторяющихся таймеров двоякий: (1) интервалы могут быть пропущены, и (2) интервалы могут быть меньше, чем ожидается между несколькими выполнениями кода таймера ... -N. Zakas, Профессиональный JavaScript для веб-разработчиков

Способ обойти это - отформатировать код таймера следующим образом:

setTimeout( function() {

       // code to be run

       setTimeout( arguments.callee, *interval* );

}, *interval* );

примечание: arguments.callee нельзя использовать в строгом режиме.

0 голосов
/ 20 июля 2011

Я не думаю, что вы сможете полагаться только на сеанс Auth для этого.

Что я хотел бы сделать, это создать новое поле в пользовательской таблице для отслеживания последней активности, что-то вроде last_activity как отметка времени mysql.Затем в вашем AppController::beforeFilter() установите это поле так, чтобы оно обновлялось с текущей датой-временем (так будет происходить с каждым запросом), но установите его так, чтобы оно пропускалось, если ваш запрос ping выполняет запрос (вы можете проверить $this->hereили, возможно, даже добавьте свой собственный параметр для других действий).

Ваш Ajax-пинг, очевидно, просто читает это поле, и, если количество минут назад превышает x, вы выходите из системы.

0 голосов
/ 20 июля 2011

Как я уже упоминал в комментарии, вы можете создать файл javascript со следующим содержимым и вызывать этот файл на всех своих страницах

setTimeout("checkSession()",1800000);
function checkSession(){
     //alert("Your session has expired due to inactivity. You will be logged out");
     window.location.reload();//or window.location="logoutAction";
}
0 голосов
/ 20 июля 2011

Очевидные способы сделать это:

  1. не вызывать session_start () в вашей конечной точке Ajax
  2. реализовать свой собственный обработчик сеанса с бэкдором, который позволяет вампропустить часть записи (например, в зависимости от состояния глобальной переменной или текущего URL)

Как неприятный хак, вы можете попробовать вызвать session_id ('dummy');или измените обработчик сеанса после вызова session_start () в конечной точке Ajax.

0 голосов
/ 20 июля 2011

Пинг AJAX, который вы описали, чаще всего используется только для поддержания активности сессии.Тот факт, что вы обращались к своему приложению во время активного сеанса, обновляет его.

Вы можете выполнить одно из следующих действий:

  • иметь сеанс фиксированной длины, например 30минут, по истечении которых он всегда истекает (не уверен, что это хорошая идея) и заставляет пинг
  • изменять логику так, чтобы вы вообще не пинговали, а когда истекает сеанс и пользователь либо перемещаетсяна новую страницу или выполняет сеанс AJAX, сервер возвращает соответствующий код состояния и / или перенаправляет пользователя на страницу входа.

Я бы выбрал 2-й вариант.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...