Таблица БД не обновляется при принудительном выходе из системы, используя ajax - PullRequest
3 голосов
/ 28 апреля 2020

Как указано в заголовке, таблица БД trace_users не обновляется , когда в течение 30 минут не происходит никаких действий , но обновляется по истечении 6 минут.

Следующий код (JS и PHP) находится внутри одного и того же php файла mno. php.

Я храню последнее действие пользователя через эту строку let lastActivity = <?php echo time(); ?> ;, присутствующее в приведенном ниже сценарии.

<?php
session_start();     
if (isset($_GET['action']) && $_GET['action'] == "logout")
{
    session_destroy(); // destroy session data in storage
    !isset($_SESSION['pageadmin']);
    $open = "false";
    $write = "0";
    $stmt = $connect->prepare("UPDATE trace_users SET open=?, write=? WHERE user_name=?");
    $usname = !empty($_SESSION['user_name']) ? $_SESSION['user_name'] : '';
    $stmt->bind_param('sss', $open, $write, $usname);
    $stmt->execute();
}
?>
<script>
    jQuery(document).ready(function($) {

        let lastActivity = <?php echo time(); ?> ;  // storing last activity of user

        let now = <?php echo time(); ?> ;

        let logoutAfter = 360;

        let timer = setInterval(function() {
            now++;
            let delta = now - lastActivity;
            console.log(delta);
            if (delta > logoutAfter) {
                clearInterval(timer);
                //DO AJAX REQUEST TO close.php
                $.ajax({
                    url: "/abc/mno.php",
                    type: 'GET',
                    data: {
                        action: 'logout'
                    }, // Line A
                    success: function(data) {
                        console.log(data); // Line B
                    },
                    error: function(jqXHR, textStatus, errorThrown) {
                        alert(textStatus);
                    }
                });
            }
        }, 1000);
    }); 
</script>

Постановка проблемы:

Мне интересно, какие изменения я должен внести в приведенный выше код, чтобы , если в течение 30 минут не происходит никаких действий (1800 секунд), тогда таблица БД также должна обновиться .

Case1 (не работает): 1800 секунд (страница выходит из системы, db не обновляется )
Case2 (Рабочая): 360 секунд (страница выходит из системы, дБ обновляется )

Значения внутри session.gc_maxlifetime равны 1440 (Локальное значение) 1440 ( Основное значение)

Это то, что я пробовал / отлаживал:

На вкладке сети я получаю метод запроса GET по истечении времени ожидания сеанса устанавливается 6 минут и 60 минут .

Ответы [ 4 ]

2 голосов
/ 03 мая 2020

Вам необходимо передать javascript какой-то постоянный UID, который идентифицирует пользователя даже после истечения сеанса .

Для упрощения я использую user_name, который уже существует в вашем коде. Но вы также можете назначить UUID для каждого пользователя, чтобы вы не могли угадать имя другого пользователя и не могли изменить его статистику.


Сначала вы передадите $_SESSION['user_name'] из PHP до закрытия JS.

let userName = "<?php echo $_SESSION['user_name']; ?>";  // don't forget to wrap the JS string value in quotes or apostrophes

Затем вы передадите его в полезную нагрузку AJAX запроса.

data: {
    action: 'logout',
    user_name: userName  // added param
},

Наконец, вы перезапишите значение который отправляется в БД (если он отправлен с полезной нагрузкой)

$usname = !empty($_SESSION['user_name']) ? $_SESSION['user_name'] : '';  // original line
if (isset($_GET['user_name']) && !empty($_GET['user_name'])) {
    $usname = $_GET['user_name'];
}
$stmt->bind_param('sss', $open, $write, $usname);  // original line

Полный обновленный код:

<?php
if (isset($_GET['action']) && $_GET['action'] == "logout")
{
    session_destroy(); // destroy session data in storage
    !isset($_SESSION['pageadmin']);
    $open = "false";
    $write = "0";
    $stmt = $connect->prepare("UPDATE trace_users SET open=?, write=? WHERE user_name=?");
    $usname = !empty($_SESSION['user_name']) ? $_SESSION['user_name'] : '';
    if (isset($_GET['user_name']) && !empty($_GET['user_name'])) {
        $usname = $_GET['user_name'];
    }
    $stmt->bind_param('sss', $open, $write, $usname);
    $stmt->execute();
}
?>
<script>
    jQuery(document).ready(function($) {

        let lastActivity = <?php echo time(); ?> ;  // storing last activity of user

        let now = <?php echo time(); ?> ;

        let logoutAfter = 10;

        let userName = "<?php echo $_SESSION['user_name']; ?>";

        let timer = setInterval(function() {
            now++;
            let delta = now - lastActivity;
            console.log(delta);
            if (delta > logoutAfter) {
                clearInterval(timer);
                //DO AJAX REQUEST TO close.php
                $.ajax({
                    url: "/abc/mno.php",
                    type: 'GET',
                    data: {
                        action: 'logout',
                        user_name: userName
                    }, // Line A
                    success: function(data) {
                        console.log(data); // Line B
                    },
                    error: function(jqXHR, textStatus, errorThrown) {
                        alert(textStatus);
                    }
                });
            }
        }, 1000);
    }); 
</script>

Несколько примечаний в конце:

  • Это плохая практика - объединять PHP, HTML и JS в одном файле.
  • Некоторые части вашего кода трудно воспроизводимы, и я должен был догадаться из контекста (например, я догадался, что сеанс уже установлен, используется jQuery, но нет <script src="...jquery.js">, есть запрос к БД, но нет отдельного импорта SQL, чтобы попробовать его быстро). Пожалуйста, прочитайте и примените знания из Как создать минимальный воспроизводимый пример в своем следующем вопросе, чтобы больше людей могли или хотят помочь вам с ним.
1 голос
/ 05 мая 2020

PHP процесс не сидит бесконечно и не имеет программной структуры как сервер al oop ala Node.js, который не позволит вам реагировать на истечение срока сеанса, так как это не процесс, который делает его недействительным, а скорее простая временная метка, связанная с сеансом, которая проверяется каждый раз, когда вы пытаетесь работать с ним.

Предлагаемое мной решение - это простой скрипт, который запускается каждые N минут для сравнения последней отметки времени активности пользователя (которая, Я предполагаю, что обновляется по запросу для этого пользователя) по истечении срока действия (в вашем случае это 30 минут). Вы также можете установить срок действия сессии до 30 минут, хотя строго это не обязательно. Если разница во времени превысит 30 минут, вы обновите отметку времени для пользователя в вашей таблице и при необходимости аннулируете его сеанс. Сценарий может быть запущен через cron или его альтернативы и go через всех пользователей, которым требуется выполнить проверку.

Не забудьте обработать случай, когда пользователь вышел из системы на сервере, но клиент не знает об этом и может продолжать отправлять запросы на выход из системы - окно оповещения о вызове довольно неясно (лучше вернуть HTTP-несанкционированный код и обрабатывать его по-другому - например, перенаправить на экран входа в систему)

1 голос
/ 28 апреля 2020

Проблема в том, что вы не изменяете ничего, что помешает истечению сеанса через N секунд, вы просто кодируете свой сценарий таким образом, чтобы он по истечении этого времени уничтожил сеанс. Сеанс g c (сборщик мусора) периодически выполняется и удаляет старые сеансы, и когда это произойдет, $_SESSION['LAST_ACTIVITY'] также будет удалено.

Вы должны либо попытаться запретить удалению сеансов g c или измените логи c в вашем приложении.

0 голосов
/ 09 мая 2020

Есть две вещи, которые нужно исправить.

1). Установите для запроса ajax значение async:false.

$.ajax({
    url: "/abc/mno.php",
      type: 'GET',
      async: false,   //  <---- ADDED ASYNC FALSE
      data: {
        action: 'logout'
    }, // Line A
     success: function(data) {
        console.log(data); // Line B
      },
     error: function(jqXHR, textStatus, errorThrown) {
         alert(textStatus);
       }
 });

2). Уничтожить сеанс после выполнения запроса SQL.

<?php
session_start();     
if (isset($_GET['action']) && $_GET['action'] == "logout")
{
    !isset($_SESSION['pageadmin']);
    $open = "false";
    $write = "0";
    $stmt = $connect->prepare("UPDATE trace_users SET open=?, write=? WHERE user_name=?");
    $usname = !empty($_SESSION['user_name']) ? $_SESSION['user_name'] : '';
    $stmt->bind_param('sss', $open, $write, $usname);
    $stmt->execute();
    session_destroy(); // destroy session data in storage <---- DESTORY AT THE END
}
?>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...