How to end the user’s session if it closes page/tab?

Asked

Viewed 3,802 times

2

When the user logs in, this user goes through the following check on all pages:

if(!isset($_SESSION['start_login'])) { // se não tiver pego tempo que logou
$_SESSION['start_login'] = time(); //pega tempo que logou
// adiciona 30 segundos ao tempo e grava em outra variável de sessão
$_SESSION['logout_time'] = $_SESSION['start_login'] + 30*60; 
}

// se o tempo atual for maior que o tempo de logout
if(time() >= $_SESSION['logout_time']) { 
header("location:logout.php"); //vai para logout

} else {
$red = $_SESSION['logout_time'] - time(); // tempo que falta
//echo "Início de sessão: ".$_SESSION['start_login']."<br>";
//echo "Redirecionando em ".$red." segundos.<br>";
}

If the user stays on the page he is redirected after 30 minutes. All right. The problem is that if the user closes the page/tab (X) he is still logged in to the system... How can I get around this? Any tips?

  • It remains logged in because $_SESSIONS are destroyed only when the browser is closed. If you still want to end the session just because it closed the tab, you will have to use AJAX.

  • @Claydersonferreira I can’t find a solution to solve this problem. Could you give me an example code for when the user closes the tab I can run a query? Ai already gave to add in the user’s table its status offline

  • 1

    I’ll try to set an example for you.

  • 1

    As $_SESSIONS nay are destroyed only when the browser is closed! You can open and close the browser several times and it will not destroy the session cookie if the option to pick up where I left off. It’s just an observation!

  • 1

    @Papacharlie, this is new for me. Thanks for the info (:

  • @Claydersonferreira for me was also new, I was looking for some questions about cookie in SO-EN one day and I came across an answer that explained this. In short, the user unchecks the option stay connected, and yet the browser keeps the cookie. :(

Show 1 more comment

1 answer

4


Come on

Add a table to your database by following the template below. It will be responsible for managing open sessions.

inserir a descrição da imagem aqui

Change the validation you already have, and switch to the code below. Remember to make the necessary modifications to work with your application.

<?php

$host   = 'localhost';
$db     = 'banco';
$user   = 'root';
$pass   = '';
$charst = 'utf8';

$pdo = new PDO("mysql:host={$host};dbname={$db};charset={$charst}", $user, $pass);

if (!isset($_SESSION['session_id'])) {

    $idAutenticado = false;
    while ($idAutenticado === false) {
        $novoID = rand();

        $consultarID = $pdo->prepare("SELECT `session_id` FROM `sessoes_abertas` WHERE `session_id` = :session_id");
        $consultarID->bindValue(':session_id', $novoID);
        $consultarID->execute();

        if ($consultarID->rowCount() === 0) {
            $idAutenticado = true;
        }
    }

    $cadastrarID = $pdo->prepare("INSERT INTO `sessoes_abertas` (`session_id`, `last_activity`, `logout_time`) VALUES (:session_id, :last_activity, :logout_time)");
    $cadastrarID->bindValue(':session_id', $novoID);
    $cadastrarID->bindValue(':last_activity', time());
    $cadastrarID->bindValue(':logout_time', time() + (30 * 60));
    $cadastrarID->execute();

    $_SESSION['session_id'] = $novoID;
} else {
    $validarID = $pdo->prepare("SELECT * FROM `sessoes_abertas` WHERE `session_id` = :session_id AND `last_activity` >= :last_activity AND `logout_time` <= :logout_time");
    $validarID->bindValue(':session_id', $_SESSION['session_id']);
    $validarID->bindValue(':last_activity', (time() - (5 * 60)); //Permite até 5 minutos de inatividade
    $validarID->bindValue(':logout_time', (time() + (30 * 60)); //30 minutos de duração pra sessão
    $validarID->execute();

    if ($validarID->rowCount() === 0) {
        unset($_SESSION['session_id']);
        header('Location: ./');
    }
}

Now we have to implement the AJAX function that will be responsible for updating the last_activity field, so we can ensure that the user is active.

Obs: the downtime is set in the first part of the code, where it is commented.

Include jQuery in your project

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>

It is possible to do without jQuery, using pure Javascript, which would be more recommended if your application does not use jQuery for other features, but since I don’t understand almost anything about JS, I’ll leave it to someone else.

The code below will make requests to a PHP script (which we will create later) at each time interval.

<script>
    function attLastActivity() {
        $.ajax({
            url: 'last-activity.php',
            type: 'GET',
            data: '',
            success: function(data) {
                //Essa função é disparada caso a requisição dê certo, se quiser implementar alguma funcionalidade, edite aqui.
            },
            beforeSend: function() {
                //Função disparada antes de fazer a requisição.
            }
        });
    }

    setInterval(attLastActivity, 30000); //Faz uma requisição a cada 30 segundos
</script>

Create a PHP file that will receive AJAX requests, the file name should be last-activity.php and add the code below.

?php

if (isset($_SESSION['session_id'])) {
    $host   = 'localhost';
    $db     = 'banco';
    $user   = 'root';
    $pass   = '';
    $charst = 'utf8';

    $pdo = new PDO("mysql:host={$host};dbname={$db};charset={$charst}", $user, $pass);

    $lastActivity = $pdo->prepare("UPDATE `sessoes_abertas` SET `last_activity` = :last_activity WHERE `session_id` = :session_id");
    $lastActivity->bindValue(':last_activity', time());
    $lastActivity->bindValue(':session_id', $_SESSION['session_id']);
    $lastActivity->execute();
}

Concluding

If the user closes the tab, and stays 5 minutes without returning, he loses the session. This time can be customized in the first part.

That way you will have it either way, but all records will continue in the database and depending on the amount of access to your application, this can get very large and reduce the performance of the database, so you can also create functions to delete the expired Ids.

I recommend doing this using cron Jobs (if you’re on Linux).

Note that it is not mandatory to use PDO to connect to the database, it depends on your application.

That’s it, remember that the code must be modified according to your needs.

  • Thank you for your time friend, I put as a topic solved because that seems to be the solution! however I will try and soon say something. Thanks again!(:

  • 1

    It is helping that we learn rs. Any questions regarding the code, just comment here that I explain you.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.