Disconnetti un utente da un sito Web quando mette in pausa il computer


11

Questo è bizzarro. Abbiamo un sito Web Laravel e su tale sito abbiamo un timer per utente, in cui ricevono 15 minuti di inattività prima di essere avviati.

Lo facciamo attraverso un timer che si trova sulla pagina in un componente di reazione, funziona come vogliamo, ma ora abbiamo un nuovo problema: se un utente è connesso e chiude il coperchio del proprio laptop, il sito Web dovrebbe avviarli . Le banche lo fanno, le scuole e le università lo fanno, anche i siti del governo lo fanno. Quindi è possibile, non so proprio come.

Usiamo i web socket, usando la libreria laravel-websocket ed Echo. Quello che vorrei vedere accadere è:

  • Una volta chiuso il laptop, si avvia alla schermata di accesso. Quindi la prossima volta che apri il laptop e accedi, e vedi il browser sei nella schermata di accesso. Non deve succedere così in fretta, ma abbiamo bisogno di un modo per inviare qualcosa al front-end, in pratica dicendo loro di aggiornare la pagina, una volta che la sessione viene uccisa, impostiamo la durata della sessione su laravel di 15 minuti.

Alcune persone hanno suggerito in altre domande simili:

  • per creare un gestore socket Web personalizzato
  • Per confrontare il cookie di sessione (nel browser) con il cookie dell'utente sul back-end.
  • Avere un timer in esecuzione sul front-end (lo facciamo, si ferma solo quando si chiude il coperchio del laptop)

Il più popolare sembra usare i web-socket, ascoltando l'utente che si disconnette e poi li avvia, il che va bene e tutto il resto, ma come si fa a inviare una richiesta a un browser che è sospeso per poi avviarli?

Ho trovato requestIdleCallback () Ma, di nuovo, non penso che sia quello che voglio se ho già un timer per il battito cardiaco sul sito. Inoltre non funziona in tutti i browser.

Sono molto perso qui su come realizzare questo, l'esempio che posso dare è:

Accedi alla tua banca, metti il ​​computer in standby, attendi 15-20 minuti, risveglia il computer, accedi e vedi che la tua banca ora ti ha nella schermata di accesso. Questo è quello che voglio . Ma non so come riuscirci.

Non è possibile inviare eventi a un browser "inattivo" dal back-end e, sebbene sì, questa dovrebbe essere una soluzione di back-end, come si aggiorna il front-end quindi, in modo che siano nella schermata di disconnessione quando si risvegliano il laptop o computer?


7
Basta impostare la data di scadenza della sessione di cottura su "adesso + 15 minuti" ... anche se potresti ancora vedere l'ultima schermata, non puoi agire in quella sessione se il cookie è scaduto. E la "schermata di avvio per accedere" - Sono abbastanza sicuro che ci sia un'impostazione del sistema operativo che disconnetterà automaticamente un computer dopo un certo periodo di inattività ..
Lars Stegelitz

1
È possibile avviare un timer Javascript ogni volta che viene caricato un sito, con lo stesso timeout del cookie di sessione ... se il timer "squilla", l'utente è rimasto inattivo per così tanto tempo. Dovresti quindi disconnetterlo (chiamata AJAX) e reindirizzare il browser alla schermata di accesso o alla schermata "mi dispiace, ti abbiamo disconnesso a causa di inattività";)
Lars Stegelitz

1
Ok, l'ho fatto, sto aggiungendo la risposta proprio ora.
Dato DT

1
così è stato utile?
Dato DT

1
@DatoDT No, uno che uso laravel, due uso già socket laravel come espresso nel mio post di apertura, due il tuo codice è molto disordinato, non OOP, non testato e non lo userei mai. Sto essenzialmente cercando una soluzione laravel.
TheWebs

Risposte:


0

AGGIORNARE

Per quanto riguarda la richiesta di WebSocket, presumo che tu stia utilizzando Laravel WebSocket con pusher. Pusher.io non supporta il timeout , puoi leggere questo articolo di supporto "Pensi di aggiungere una funzionalità di timeout della connessione alla libreria client di Pusher-js di canali?" . Puoi provarlo se abiliti la modalità debug di Laravel ( APP_DEBUG=true dentro .env ) e inizi laravel-websocketsdal terminale ( php artisan websockets:serve) in modo da poter vedere gli eventi del registro di output. Se si tenta di chiudere il coperchio del portatile o un set di computer in modalità di ibernazione ( sleep ), non sarà possibile visualizzare alcun messaggio per quanto riguarda questo evento. Non puoi farlo con il pusherprotocollo. C'è l' evento Presencemember_removed , ma ciò si innesca solo quando chiudi la scheda o quando esci. Ovviamente puoi attivare l'evento personalizzato del tuo client sul canale di presenza, ma per farlo devi anche impostare un timer sul lato client e dovrai creare un fornitore di servizi per il laravel-websocketsserver come questo problema github "Esisti un modo per implementare webhook? " .

Alcune persone hanno suggerito in altre domande simili:

...

  • Avere un timer in esecuzione sul front-end ( lo facciamo, si ferma solo quando si chiude il coperchio del laptop )

Ciò accade perché i timer client interrompono l'esecuzione in letargo, quindi continuano da dove erano prima. Ma se usi una variabile di data per risparmiare tempo , quella variabile non verrà aggiornata quando il computer andrà in letargo, quindi saprai quando si spegnerà controllando quella variabile di data che rispetto all'ora corrente avrà un significato differenza e sarà maggiore dell'intervallo del timer.

Implementazione della logica temporale nel client

Puoi anche vedere questa implementazione in questo Q / A correlato : è possibile rilevare eventuali browser desktop quando il computer riprende dallo stato di sospensione?

È possibile impostare un timer nel client per l'esecuzione ogni minuto. Non faremo affidamento sull'intervallo del timer , ma invece quel timer controllerà una variabile di data dell'ambito esterno se l'intervallo di tempo dall'ultimo timer è maggiore di 15minuti; se lo è, allora significa che il browser / JS fermato l'esecuzione, per qualche motivo , forse la sospensione del dispositivo ( il sonno ) e quindi reindirizzare l'utente al percorso di logout.

Esempio di codice client JS:

// Set a variable to check previous time
let clientSession = new Date;

// Setup the client session checking timer
let clientSessionTimer = setInterval(() => {
  const now = new Date;
  // Get how many seconds have passed since last check
  const secondsSpan = (now - clientSession) / 1000;

  // If the 1 minute timer has exceeded 15 minutes trigger logout and clear timer
  if (secondsSpan > (60 * 15)) {
    // For some reason JS halted execution, so we'll proceed with logging out
    clearInterval(clientSessionTimer);
    window.location.href = '/logout/session'
  } else {
    // The timer runs as it should, update the clientSession time
    clientSession = now;
  }

}, 1000 * 60);

Puoi controllare questo semplice esempio ma usando qui il 1secondo timer con 15secondi di disconnessione . È meglio testarlo su un laptop con la chiusura del coperchio e quindi riaprirlo dopo 15 secondi al minuto due, perché se si hanno molti programmi in esecuzione, il computer impiega un po 'di tempo per salvare lo stato della memoria in modo da completare la modalità di ibernazione e interrompere l'esecuzione.

Esempio di Web Workers

Puoi persino utilizzare l' API Web Workers per configurare un Web worker in modo che sia molto più sicuro:

Codice JS della pagina:

const logoutWorker = new Worker('logoutWorker.js');
logoutWorker.onmessage = function (ev) {

  if (ev && ev.data === 'wakeup') {
    logoutWorker.terminate();
    // window.location.href = '/logout/session'
  } else {
    // The timer runs as it should, nothing to do
  }
}

logoutWorker.jsCodice lavoratore Web :

let clientSession = new Date();

let clientSessionTimer = setInterval(() => {
  const now = new Date;
  const secondsSpan = (now - clientSession) / 1000;

  if (secondsSpan > 15) {
    postMessage('wakeup'); // Send a message wakeup to the worker page
    clearInterval(clientSessionTimer); // Clear the timer
  } else {
    clientSession = now; // Update the clientSession timer variable
    postMessage('update'); // And post a message to the page ONLY IF needed
  }
}, 1000);

Puoi anche controllare l'esempio di Web Worker con lo stesso 15timer di secondi qui .


Questo ti disconnette dopo 15 secondi, non importa quale sia, non è sicuro che questo è quello che sta cercando.
Islam Elshobokshy

@IslamElshobokshy hai ragione, grazie per la cattura. Ho dimenticato di aggiornare la clientSessionvariabile. Puoi controllare di nuovo la mia risposta, ho persino aggiunto un esempio di Web Worker.
Christos Lytras,

Aggiorna gli esempi di esempio che non funzionano ancora. Il primo ti disconnette dopo 15 secondi, non importa quale. Il secondo non ti disconnette mai.
Islam Elshobokshy

@IslamElshobokshy L'ho aggiornato ovviamente. Prima aveva un problema e ora funziona come previsto. Si prega di ridisegnare la pagina se non si è o forse si aggiunge un parametro simile ?v=1alla fine.
Christos Lytras,

1
Ottima soluzione + 3
AmerllicA

0

Innanzitutto, espandiamo il motivo per cui i siti Web bancari ti disconnettono dopo 15 minuti senza attività. È un requisito PCI per la sicurezza.

Requisito 8.1.8 PCI-DSS :

8.1.8 Se una sessione è stata inattiva per più di 15 minuti, richiedere all'utente di riautenticare per riattivare il terminale o la sessione.

Per raggiungere questo obiettivo, la soluzione è in realtà molto più primitiva di quanto immagini . Non richiede né l'uso di websocket né la conoscenza dello stato della macchina del client (sleep o wake o altrimenti). Tutto ciò che serve è conoscere il tempo tra la richiesta corrente usando quella sessione e l'ultima richiesta usando la stessa sessione e assicurarsi che non siano distanti più di 15 minuti. Se lo sono, l'utente deve essere nuovamente autenticato. In caso contrario, puoi procedere con la richiesta.

Il messaggio "timeout della sessione"

Probabilmente ti starai quindi chiedendo (se è così semplice) come appare il messaggio di timeout della sessione quando metti il ​​computer in standby e lo riattivi. Questa parte è ingannevolmente semplice.

Quando il computer viene messo in sospensione, il browser disconnette effettivamente tutte le connessioni TCP / IP che a loro volta chiudono il ciclo degli eventi nel motore javascript. Quindi i timer non funzionano. Ma quando il browser si sveglia di nuovo tenta di aggiornare alcune cose tra cui la pagina stessa. Pertanto, quando la pagina viene aggiornata, la richiesta torna al server invocando il server per richiedere la riautenticazione dell'utente.

Tuttavia, questo non terrà conto del messaggio javascript modale (se è quello a cui ti riferisci) che alcuni siti web bancari fanno. Inoltre, non tutti i browser eseguono un aggiornamento intenso della pagina in tutti gli scenari. Quindi può essere adottato un altro approccio. Invece di avere un timer nel browser che scade dopo 15 minuti, puoi semplicemente memorizzare il tempo di caricamento della pagina in javascript come timestamp e avere un timeout di intervallo di 1 secondo che confronta tale timestamp con quello attuale del computer. Se sono distanti più di 15 minuti, la sessione deve essere terminata.

window.onload = function() {

    sessionStart = Date.now();
    timer = setInterval(function() {
        if (Date.now() - sessionStart > 15 * 60 * 1000) {
            clearTimeout(timer);
            alert("Session Timed out!");
            window.location = "http://www.example.com/login";
        }
    }, 1000);


};

Anche se il computer si spegne e il timer si arresta, la sessione alla fine si spegnerà sul lato server ( vedere la sezione seguente per i dettagli ) e quando il computer si riattiva nuovamente il timer con un intervallo di 1 secondo alla fine si riavvierà, invocando il messaggio (come se l'utente è scaduto mentre il computer dormiva). Il tempo perso tra il momento in cui il computer è andato in standby e il momento in cui il computer si sveglia non avrà importanza poiché il timestamp rimarrà in memoria. La disconnessione tra client e server non è importante perché non è necessario comunicare queste informazioni affinché la sessione venga terminata correttamente sul lato server. Il server può eseguire la propria garbage collection e terminare la sessione senza comunicazione dal client (ovvero in modo asincrono ).

Che ci crediate o no, alle banche non interessa l'attività all'interno del cliente. A loro interessa solo l'attività di richiesta al server. Quindi, se ti stai chiedendo come mantengono viva la sessione per più di 15 minuti quando l'utente è sulla stessa pagina per così tanto tempo, semplicemente inviano una richiesta AJAX in background per aggiornare la sessione dopo aver chiesto all'utente se ancora voglio continuare.

Questo può essere fatto nello stesso onloadcallback di eventi che abbiamo usato in precedenza in questo modo:

window.onload = function() {

    sessionStart = Date.now();
    timer = setInterval(function() {
        if (Date.now() - sessionStart > 10 * 60 * 1000) {
           if (confirm("Your session is about to timeout. Do you wish to continue?")) {
                // send ajax request to refresh session TTL here
                // reset the timer
                sessionStart = Date.now();
            }
        } else if (Date.now() - sessionStart > 15 * 60 * 1000) {
            clearTimeout(timer);
            alert("Session Timed out!");
            window.location = "http://www.example.com/login";
        }
    }, 1000);


};

Gestione della fine della sessione sul lato server

Per gestire la fine della sessione sul lato server ci sono diversi approcci. A seconda di quale usi, avrai bisogno di tattiche diverse. Uno sta usando il gestore di sessioni predefinito di PHP e sta impostando la session.max_lifetimescadenza dopo 15 minuti (questo cancella i dati della sessione interamente sul lato server invalidando così il cookie del client).

Se si lascia fare il meccanismo del gestore di sessione predefinito, è possibile che si verifichino problemi a seconda del gestore utilizzato (file, memcached, redis, personalizzato, ecc.).

Con i file (gestore predefinito) la garbage collection avviene in due modi:

  • La maggior parte dei sistemi basati su Debian eseguono il proprio GC attraverso un cron job (che funziona alla grande per il tuo scenario)
  • Altre distro consentono al meccanismo GC predefinito di PHP di gestirlo, che si basa su un risultato probabilistico da ogni richiesta in arrivo a PHP che controlla i file mtime sui file di sessione ed elimina quelli passati session.max_lifetime. Il problema con questo approccio è che su siti a basso traffico una sessione potrebbe potenzialmente rimanere lì a lungo sul server fino a quando non arrivano richieste sufficienti (a seconda del session.gc_probabilitypunteggio) per invocare il GC per ripulire i file di sessione.

Con i gestori memcached e redis based non hai questo problema. Gestiranno l'eliminazione automatica della memoria. Le sessioni potrebbero rimanere nella memoria fisica per un certo periodo di tempo, ma il demone non sarà in grado di accedervi. Se sei preoccupato per questo bit per la sicurezza, puoi crittografare le sessioni a riposo o trovare un archivio chiave / valore con memoria più rigida che elimina il meccanismo GC.

Con un gestore di sessione personalizzato dovrai creare il tuo meccanismo GC. Attraverso SessionHandlerInterfaceimplementeresti un gcmetodo che ti concede l'intervallo di durata massima della sessione e saresti responsabile di verificare se la sessione ha superato la sua durata in base a questo intervallo e fare la tua garbage collection da lì.

È inoltre possibile impostare un end-point separato che controlla la sessione TTL (tramite una richiesta AJAX asincrona sul lato client) e restituisce una risposta se la sessione è scaduta (forzando il javascript a riautenticare l'utente).


0

Quindi Idea è dietro setInterval e Sockets, setInterval è supportato nella maggior parte dei browser e javascript WbsocketApi è supportato in quasi tutti i browser.

Breve panoramica: setInterval () - questo comportamento della funzione segue quando il computer è in modalità sospensione / sospensione / ibernazione viene messo in pausa e quando si è in modalità di risveglio riprende.

Il seguente codice fa quanto segue, all'inizio (forse allo stesso tempo, ma) avvia php server_socket ascoltando le connessioni,

di javascript websocket api invia il timestamp corrente in millisecondi di timestamp Unix in ogni 2 secondi puoi avere 1 secondo dipende da te.

dopo che il socket del server php sta ricevendo questa volta e controlla se ha qualcosa come la volta precedente da confrontare, quando il codice viene istanziato per la prima volta php non ha niente come la volta precedente per confrontarlo con l'ora che è stata inviata dal websocket javascript, quindi php non fa altro che salvare questa volta nella sessione chiamata "prev_time" e attende che i dati di un'altra ora vengano ricevuti dal socket javascript, quindi qui inizia il secondo ciclo. quando il server php inserisce nuovi dati temporali da WebsocketApi javascript controlla che abbia qualcosa di simile al tempo precedente per confrontarli con questi dati temporali appena ricevuti, significa che php controlla se esiste una sessione chiamata 'prev_time', come siamo nel secondo ciclo php scopre che esiste, afferra il suo valore e segue$diff = $new_time - $prev_time, $ diff sarà di 2 secondi o 2000 millisecondi perché ricorda che il nostro ciclo setInterval si verifica ogni 2 secondi e il formato dell'ora che stiamo inviando è in millisecondi,

di php controlla if($diff<3000)se la differenza è inferiore a 3000 se sa che l'utente è attivo, di nuovo puoi manipolare questi secondi come desideri, scelgo 3000 perché possibile latenza nella rete che è quasi impossibile ma sai che sono sempre cauto quando si tratta di reti, quindi continuiamo, quando php determina che l'utente è attivo, php reimposta la sessione "prev_time" con il valore di $new_timecui è stato appena ricevuto e solo a scopo di test invia un messaggio al socket javascript,

ma se $diffè più di 3000 significa che qualcosa ha messo in pausa il nostro setInterval e c'è solo un modo in cui può succedere e penso che tu sappia già quello che sto dicendo, quindi nella elselogica di ( if($diff<3000)) puoi disconnettere l'utente distruggendo una sessione specifica e se tu vuoi reindirizzare puoi inviare del testo al socket javacript e creare una logica che verrà eseguita a window.location = "/login"seconda del testo, ecco qui è il codice:

Innanzitutto è il file index.html solo per caricare javascript:

<html>
    <body>
        <div id="printer"></div>
        <script src="javascript_client_socket.js"></script>
    </body>
</html>

allora è javascript non è davvero ben codificato ma puoi capire LEGGI I COMMENTI SONO IMPORTANTI:

var socket = new WebSocket('ws://localhost:34237'); // connecting to socket
    // Open the socket
socket.onopen = function(event) { // detecting when connection is established
        setInterval(function(){ //seting interval for 2 seconds
            var date = new Date(); //grabing current date
            var nowtime = Date.parse(date); // parisng it in miliseconds
            var msg = 'I am the client.'; //jsut testing message


            // Send an initial message
            socket.send(nowtime); //sending the time to php socket
    },2000);

};


// Listen for messages
socket.onmessage = function(event) { //print text which will be sent by php socket 
    console.log('php: ' + event.data);
};

// Listen for socket closes
socket.onclose = function(event) {
    console.log('Client notified socket has closed', event);
};

ora qui fa parte del codice php, non ti preoccupare c'è anche il codice completo ma questa parte è in realtà ciò che fa i lavori sopra menzionati incontrerai anche altre funzioni ma sono per la decodifica e il lavoro con i socket javascript quindi è la cosa giusta qui LEGGI I COMMENTI SONO IMPORTANTI:

<?php 
            $decoded_data = unmask($data /* $data is actual data received from javascript socket */); //grabbing data and unmasking it | unmasking is for javascript sockets don't mind this
            print("< ".$decoded_data."\n");
            $response = strrev($decoded_data);
            $jsTime = (int) $decoded_data; /* time sent by javascript in MILISECONDS IN UNIX FORMAT  */
            if (isset($_SESSION['prev_time'])) { /** check if we have stored previous time in the session */
               $prev_time = (int) $_SESSION['prev_time']; /** grabbing the previous time from session */
               $diff = $jsTime-$prev_time; /** getting the difference newly sent time and previous time by subtracting */
               print("$jsTime - $prev_time = $diff"); /** printing the difference */
               if($diff<3000){ /** checking if difference is less than 3 second if it is it means pc was not at sleep
                               *** you can manipulate and have for example 1 second = 1000ms */
                    socket_write($client,encode("You are active! your pc is awakend"));
                    $_SESSION['prev_time'] = $jsTime; /** saving newly sent time as previous time for future testing whcih will happen in two seconds in our case*/
                }else { /** if it is more than 3 seconds it means that javascript setInterval function was paused and resumed after 3 seconds 
                            ** So it means that it was at sleep because when your PC is at sleep/suspended/hibernate mode setINterval gets pauesd */
                    socket_write($client,encode("You are not active! your pc is at sleep"));
                    $_SESSION['prev_time'] = $jsTime;
                }
            }else { /** if we have not saved the previous time in session save it  */
                $_SESSION['prev_time'] = $jsTime;
            }

            print_r($_SESSION);

?>

Ed ecco il codice completo di php:

<?php
//Code by: Nabi KAZ <www.nabi.ir>
session_abort();
// set some variables
$host = "127.0.0.1";
$port = 34237;
date_default_timezone_set("UTC");


// don't timeout!
set_time_limit(0);

// create socket
$socket = socket_create(AF_INET, SOCK_STREAM, 0)or die("Could not create socket\n");

// bind socket to port
$result = socket_bind($socket, $host, $port)or die("Could not bind to socket\n");

// start listening for connections
$result = socket_listen($socket, 20)or die("Could not set up socket listener\n");

$flag_handshake = false;
$client = null;
do {
    if (!$client) {
        // accept incoming connections
        // client another socket to handle communication
        $client = socket_accept($socket)or die("Could not accept incoming connection\n");
    }

    $bytes =  @socket_recv($client, $data, 2048, 0);
    if ($flag_handshake == false) {
        if ((int)$bytes == 0)
            continue;
        //print("Handshaking headers from client: ".$data."\n");
        if (handshake($client, $data, $socket)) {
            $flag_handshake = true;
        }
    }
    elseif($flag_handshake == true) {

        /*
        **** Main section for detectin sleep or not **
        */
        if ($data != "") {
            $decoded_data = unmask($data /* $data is actual data received from javascript socket */); //grabbing data and unmasking it | unmasking is for javascript sockets don't mind this
            print("< ".$decoded_data."\n");
            $response = strrev($decoded_data);
            $jsTime = (int) $decoded_data; /* time sent by javascript in MILISECONDS IN UNIX FORMAT  */
            if (isset($_SESSION['prev_time'])) { /** check if we have stored previous time in the session */
               $prev_time = (int) $_SESSION['prev_time']; /** grabbing the previous time from session */
               $diff = $jsTime-$prev_time; /** getting the difference newly sent time and previous time by subtracting */
               print("$jsTime - $prev_time = $diff"); /** printing the difference */
               if($diff<3000){ /** checking if difference is less than 3 second if it is it means pc was not at sleep
                               *** you can manipulate and have for example 1 second = 1000ms */
                    socket_write($client,encode("You are active! your pc is awakend"));
                    $_SESSION['prev_time'] = $jsTime; /** saving newly sent time as previous time for future testing whcih will happen in two seconds in our case*/
                }else { /** if it is more than 3 seconds it means that javascript setInterval function was paused and resumed after 3 seconds 
                            ** So it means that it was at sleep because when your PC is at sleep/suspended/hibernate mode setINterval gets pauesd */
                    socket_write($client,encode("You are not active! your pc is at sleep"));
                    $_SESSION['prev_time'] = $jsTime;
                }
            }else { /** if we have not saved the previous time in session save it  */
                $_SESSION['prev_time'] = $jsTime;
            }

            print_r($_SESSION);

           /*
        **** end of Main section for detectin sleep or not **
        */ 


        }
    }
} while (true);

// close sockets
socket_close($client);
socket_close($socket);
$client = null;
$flag_handshake = false;

function handshake($client, $headers, $socket) {

    if (preg_match("/Sec-WebSocket-Version: (.*)\r\n/", $headers, $match))
        $version = $match[1];
    else {
        print("The client doesn't support WebSocket");
        return false;
    }

    if ($version == 13) {
        // Extract header variables
        if (preg_match("/GET (.*) HTTP/", $headers, $match))
            $root = $match[1];
        if (preg_match("/Host: (.*)\r\n/", $headers, $match))
            $host = $match[1];
        if (preg_match("/Origin: (.*)\r\n/", $headers, $match))
            $origin = $match[1];
        if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/", $headers, $match))
            $key = $match[1];

        $acceptKey = $key.'258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
        $acceptKey = base64_encode(sha1($acceptKey, true));

        $upgrade = "HTTP/1.1 101 Switching Protocols\r\n".
            "Upgrade: websocket\r\n".
            "Connection: Upgrade\r\n".
            "Sec-WebSocket-Accept: $acceptKey".
            "\r\n\r\n";

        socket_write($client, $upgrade);
        return true;
    } else {
        print("WebSocket version 13 required (the client supports version {$version})");
        return false;
    }
}

function unmask($payload) {
    $length = ord($payload[1]) & 127;

    if ($length == 126) {
        $masks = substr($payload, 4, 4);
        $data = substr($payload, 8);
    }
    elseif($length == 127) {
        $masks = substr($payload, 10, 4);
        $data = substr($payload, 14);
    }
    else {
        $masks = substr($payload, 2, 4);
        $data = substr($payload, 6);
    }

    $text = '';
    for ($i = 0; $i < strlen($data); ++$i) {
        $text .= $data[$i] ^ $masks[$i % 4];
    }
    return $text;
}

function encode($text) {
    // 0x1 text frame (FIN + opcode)
    $b1 = 0x80 | (0x1 & 0x0f);
    $length = strlen($text);

    if ($length <= 125)
        $header = pack('CC', $b1, $length);
    elseif($length > 125 && $length < 65536)$header = pack('CCS', $b1, 126, $length);
    elseif($length >= 65536)
    $header = pack('CCN', $b1, 127, $length);

    return $header.$text;
}

NOTA LEGGI: ​​la $new_timevariabile è $jsTimenel codice

crea una cartella e copialo e incollalo nei file esegui php socket con il comando: php -f server_socket.php vai su localhost e testalo aprendo la console per vedere i messaggi dirà "sei attivo" o "non sei attivo" (quando vieni dal sonno); la tua esecuzione avverrà quando l'utente verrà dallo stato di sospensione non quando è in stato di sonno, poiché in quel momento tutto viene memorizzato nella cache nel file di paging (windows) o in swap (linux)


crea una cartella e copialo e incollalo nei file esegui php socket con il comando: php -f server_socket.php vai su localhost e testalo aprendo la console per vedere i messaggi dirà "sei attivo" o "non sei attivo" (quando vieni dal sonno); la tua esecuzione avverrà quando l'utente verrà dallo stato di sospensione non quando è in stato di sonno, poiché in quel momento tutto viene memorizzato nella cache nel file di paging (windows) o in swap (linux)
Dato DT

0

Penso di avere un'idea, hai discusso molto su come funziona il sistema di login / logout bancario.

Caso 1: accesso della pagina Web all'utente per un tempo illimitato se l'utente è attivo

Ogni volta che l'utente ha effettuato l'accesso, avvia un timer sul back-end (imposta il limite di tempo come desideri), diciamo 15 minuti. Ora cosa significa ?? Significa che se l'utente non svolge alcuna attività sulla pagina Web, verrà disconnesso.

Ora, dal lato frontale, puoi inviare l'attività dell'utente al tuo backend (potrebbe essere inviato tramite socket o polling lungo), che in pratica ripristinerà il timer e l'utente potrà utilizzare la pagina Web attivamente per tutto il tempo che desidera.

Se l'utente mette il PC in standby, il timer non si reimposta e puoi invalidare la sessione al termine del timer.

Se si desidera invalidare la sessione utente non appena mettono in pausa il proprio PC, è possibile impostare il limite del tempo di convalida della sessione. Ad esempio, quando l'utente accede, creeremo la sessione che sarà valida solo per 10 secondi e una volta ricevuta la richiesta di attività dell'utente, possiamo ripristinare il timer e fornire una nuova chiave di sessione.

Spero che questo ti aiuta. Fammi sapere se hai qualche domanda.


-1

Ho scritto una sceneggiatura per rilevare se la macchina è andata a dormire. L'idea è che quando la macchina è in stato d'animo tutti gli script si fermano. Pertanto, se teniamo traccia dell'ora corrente entro un intervallo di tempo. Ogni volta che timeInterval attiva l'ora corrente meno (-) la nuova ora dovrebbe essere abbastanza vicina a timeInterval. Pertanto, se vogliamo verificare se il timer è rimasto inattivo per il tempo X, possiamo verificare se la differenza oraria è maggiore di X.

Il colpo di esempio controlla se il computer è stato messo in sospensione per più di 15 secondi. Si noti che quando si mette il computer in modalità sospensione, ci vogliono circa altri 15 secondi per ideare tutti i processori. (Quando testato su MY PC).

(function() {
    this.SleepTimer = function() {
        // console.log('sleep timer initiated');
        // Create global element references
        this.sleepTimer = null;
        this.maxTime = null;
        this.curDate = null;
        this.newDate = null;
        this.timer = null;
        this.timeInterval = 1000;

        this.sleepTimer = new CustomEvent("sleepTimer", {
		    "detail": {
		    	"maxTime":this.maxTime,
				"idelFor": this.newDate - this.curDate,
				"timer": this.timer
			}
		});

        // Define option defaults
        var defaults = {
            maxTime: 10000,
            timeInterval: 1000,
            autoStart: true,
            console: false,
            onStart: null,
            onIdel: null
        }
        // Create options by extending defaults with the passed in arugments
        if (arguments[0] && typeof arguments[0] === "object") {
            this.options = extendDefaults(defaults, arguments[0]);
        }
        if (this.options.timeInterval) {
            this.timeInterval = Math.max(1000, this.options.timeInterval);
            this.maxTime = Math.max(this.options.maxTime, 10000);
        } else {
        	this.options = defaults;
        }

        if(this.options.autoStart === true) this.start()
        // Utility method to extend defaults with user options
        
    }
    function extendDefaults(source, properties) {
        var property;
        for (property in properties) {
            if (properties.hasOwnProperty(property)) {
                source[property] = properties[property];
            }
        }
        return source;
    }
    SleepTimer.prototype.start = function(){
        var _ = this;
    	this.options.onStart()
        this.curDate = Date.now();

        this.timer = setInterval(function() {
            _.newDate = Date.now();
            var diff = _.newDate - _.curDate;

            // for debugging
            if(_.options.console && diff > _.timeInterval){
            	console.log('Your PC was idel for ' + diff / 1000 + 's of ' + _.maxTime /1000 + 's. TimeInterval is set to ' + _.timeInterval / 1000 + 's');
            }
            
            if (diff < _.maxTime) {
                _.curDate = _.newDate;
            } else {
            	_.options.onIdel();
                // alert('You have been idle for ' + diff / 1000 + 's');
                clearTimeout(_.timer);
            }
        }, this.timeInterval); // seconds
    }
}());

var sleepTimer = new SleepTimer({
	maxTime: 15000,
	console: true,
	onStart: function(){
		console.log('sleepTimer started.');
	},
	onIdel: function(){
		alert('Your session expired! Please login again.');
	}
});


Per favore, spiega perché questo non funzionerebbe, se non nel tuo caso
Lasithds il

-1

Ho implementato esattamente lo stesso requisito utilizzando AWS Cognito, con Lambda Authorizer e Redis, non posso condividere il codice in questa fase ma posso dirti tutto su come viene implementato con questi componenti, gli stessi concetti possono essere usati con altri componenti non AWS.

In primo luogo con l'implementazione di un logout di inattività, dovrai farlo sul lato server, come se qualcuno semplicemente spegnesse il proprio computer, il sito Web front-end non li disconnetterebbe. Ho usato il concetto di ACTIVEutenti. Quando gli utenti eseguono l'autenticazione, memorizzo con un TTL di 15 minuti in Redis una voce con una chiave del loro usernamee un valore di ACTIVE(può essere nome utente + sessionid se si desidera consentire più sessioni per un determinato utente contemporaneamente).

Nei miei Authorizer personalizzati quando un utente è ACTIVEe hanno un token valido, concedo loro l'accesso alla risorsa protetta E, cosa più importante, faccio un altro inserimento in Redis con username& ACTIVE.

Ogni volta che l'utente si disconnette, li disconnetto nella mia soluzione di gestione delle identità (Cognito) e li contrassegno come INACTIVE. Nota che se un utente non raggiunge l'API entro 15 minuti, non avrà più accesso ACTIVEal proprio nome utente e non sarà più in grado di accedere all'API e dovrà accedere di nuovo, per cui verrà reindirizzato.

Ci sono molte cose da considerare con questo approccio, per prima cosa spesso gli autori memorizzano nella cache i risultati per un certo periodo di tempo e, se si dice che il risultato viene memorizzato nella cache per 5 minuti come esempio, è possibile che l'utente venga disconnesso in 10 minuti come utente potrebbe colpire la cache anziché l'autore, il che non aggiornerebbe la ACTIVEvoce.

È anche importante assicurarsi che tutto ciò che si utilizza per memorizzare se un determinato utente ACTIVEsia altamente disponibile e si ripristinerà rapidamente in caso di errore.

L'approccio dell'uso di un archivio cache in questo modo è simile al modo in cui l'invalidazione del token viene adattata ai protocolli di autorizzazione senza stato come OAuth2.

Usiamo questo approccio da alcuni mesi, sembra funzionare bene per noi, può essere un po 'un requisito fastidioso da gestire, mi sarei aspettato nel mondo AWS che ci fosse un pronto per l'uso della soluzione box per questo, ma non c'era nessuno di cui parlare.


Siamo anche sopravvissuti a un test con penna (; questo è da dove inizialmente è arrivato il nostro requisito, la nostra applicazione è un prodotto basato sui servizi finanziari e abbiamo dovuto implementarlo come requisito.
Snickers3192
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.