How to end the user session if this page is closed?

2

When the user logs in, this user goes through the following checks 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 it is redirected after 30 minutes. It works fine. The problem is that if the user closes the page / tab (X) it remains logged in the system ... How can I get around this? Any tips?

    
asked by anonymous 26.02.2016 / 21:26

1 answer

4

Let's go

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

Changethevalidationyoualreadyhave,andchangethecodebelow.Remembertomakethenecessarymodificationstoworkwithyourapplication.

<?php$host='localhost';$db='banco';$user='root';$pass='';$charst='utf8';$pdo=newPDO("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 guarantee that the user is active.

Obs: The downtime is defined in the first part of the code, where it is commented out.

Include jQuery in your project

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

ItispossibletodowithoutjQuery,usingpureJavaScript,whichwouldbemoreadvisableifyourapplicationdoesnotusejQueryforotherfeatures,butsinceIdonotunderstandalmostanythingaboutJS,I'llleaveittosomeoneelse.

ThecodebelowwillmakerequeststoaPHPscript(whichwewillcreatelater)ateachtimeinterval.

<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 the AJAX requests, the filename 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();
}

Completing

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.

This way, you will have to either, 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 database performance, so you can also create functions to delete IDs that have expired.

I recommend doing this using cron jobs (if you are in a Linux environment).

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 should be modified to suit your needs.

    
26.02.2016 / 23:29