Log pengguna keluar dari situs web ketika mereka tidur komputer mereka

11

Ini yang aneh. Kami memiliki situs web Laravel, dan di situs tersebut kami memiliki penghitung waktu per pengguna, di mana mereka mendapatkan 15 menit tidak aktif sebelum di-boot.

Kami melakukan ini melalui penghitung waktu yang duduk di halaman dalam komponen reaksi, itu berfungsi seperti yang kita inginkan, tetapi sekarang kita memiliki masalah baru: Jika pengguna masuk dan menutup tutup laptop mereka situs web harus mem-bootnya . Bank melakukan ini, Sekolah dan Universitas melakukan ini, Situs pemerintah juga melakukan ini. Jadi itu mungkin, tidak yakin bagaimana caranya.

Kami memang menggunakan soket web, menggunakan perpustakaan laravel-websockets dan Echo. Yang ingin saya lihat adalah:

  • Setelah Anda menutup boot laptop Anda, Anda ke layar login. Jadi lain kali Anda membuka laptop dan login, dan melihat browser Anda berada di layar login. Itu tidak harus terjadi secepat itu, tetapi kita perlu cara untuk mengirim sesuatu ke ujung depan pada dasarnya memberitahu mereka untuk menyegarkan halaman, setelah sesi terbunuh, kita mengatur seumur hidup sesi pada laravel 15 menit.

Beberapa orang telah menyarankan dalam pertanyaan serupa lainnya:

  • untuk membuat penangan soket-web khusus
  • Untuk membandingkan cookie sesi (di browser) dengan cookie pengguna di bagian belakang.
  • Untuk menjalankan timer di ujung depan (kami lakukan, itu hanya berhenti ketika Anda menutup penutup laptop)

Yang paling populer tampaknya menggunakan soket web, mendengarkan pengguna untuk memutuskan sambungan dan kemudian mem-boot-nya, yang baik-baik saja dan semuanya, tetapi kemudian bagaimana Anda mengirim permintaan ke browser yang ditangguhkan lalu mem-boot-nya?

Saya telah menemukan requestIdleCallback () Tapi sekali lagi, saya tidak berpikir ini yang saya inginkan jika saya sudah memiliki timer detak jantung di situs. Ini juga tidak berfungsi di semua browser.

Saya sangat tersesat di sini tentang cara mencapai ini, contoh yang bisa saya berikan adalah:

Masuk ke bank Anda, matikan komputer Anda, tunggu 15-20 menit, nyalakan komputer, masuk dan lihat bank Anda sekarang sudah menempatkan Anda di layar login. Itu yang saya inginkan . Tapi saya tidak tahu bagaimana mencapainya.

Anda tidak dapat mengirim acara ke browser "sedang tidur" dari ujung belakang, dan sementara ya ini harus menjadi solusi ujung belakang, bagaimana Anda memperbarui ujung depan kemudian, sehingga mereka berada di layar logout ketika mereka membangunkan kembali laptop atau komputer?

TheWebs
sumber
7
Cukup tetapkan tanggal masak sesi berakhir menjadi "sekarang + 15 menit" ... meskipun Anda mungkin masih melihat layar terakhir, Anda tidak dapat bertindak di sesi itu jika cookie telah kedaluwarsa. Dan "boot to login screen" - Saya cukup yakin bahwa ada pengaturan OS yang secara otomatis akan logout komputer setelah tidak ada waktu tertentu ..
Lars Stegelitz
1
Anda bisa init timer Javascript setiap kali situs dimuat, dengan batas waktu yang sama dengan cookie sesi Anda ... jika timer "berdering", pengguna tidak aktif untuk waktu yang lama. Anda kemudian akan mengeluarkannya (panggilan AJAX) dan mengarahkan browser ke layar masuk atau layar "maaf, kami telah mengeluarkan Anda karena tidak aktif";)
Lars Stegelitz
1
Oke saya sudah melakukannya saya menambahkan jawabannya sekarang.
Dato DT
1
jadi apakah ini berguna?
Dato DT
1
@ DatoDT Tidak, Satu saya menggunakan laravel, dua saya sudah menggunakan soket laravel seperti yang dinyatakan dalam posting pembukaan saya, dua kode Anda sangat berantakan, bukan OOP, tidak diuji dan saya tidak akan pernah menggunakannya. Saya pada dasarnya mencari solusi laravel.
TheWebs

Jawaban:

0

MEMPERBARUI

Mengenai permintaan WebSocket, saya menganggap Anda menggunakan Laravel WebSockets dengan pusher. Pusher.io tidak mendukung batas waktu , Anda dapat membaca artikel dukungan ini "Apakah Anda berencana untuk menambahkan fitur batas waktu koneksi ke perpustakaan klien Channels pusher-js?" . Anda dapat mengujinya jika Anda mengaktifkan mode debug Laravel ( APP_DEBUG=true di dalam .env ) dan mulai laravel-websocketsdari terminal ( php artisan websockets:serve) sehingga Anda dapat melihat acara log keluaran. Jika Anda mencoba untuk menutup penutup laptop atau mengatur komputer ke mode hibernasi ( tidur ), Anda tidak akan melihat pesan apa pun mengenai acara ini. Anda tidak dapat melakukannya dengan pusherprotokol. Ada acara Kehadiranmember_removed , tetapi itu hanya dipicu ketika Anda menutup tab atau keluar. Tentu saja Anda dapat memicu acara khusus klien Anda ke saluran keberadaan, tetapi untuk melakukan itu Anda juga memerlukan pengaturan waktu ke sisi klien dan Anda harus membuat penyedia layanan untuk laravel-websocketsserver seperti masalah github ini "Ada cara untuk mengimplementasikan webhooks? " .

Beberapa orang telah menyarankan dalam pertanyaan serupa lainnya:

...

  • Untuk menjalankan timer di ujung depan ( kami lakukan, itu hanya berhenti ketika Anda menutup penutup laptop )

Itu terjadi karena penghitung waktu klien menghentikan eksekusi pada hibernasi, sehingga mereka melanjutkan dari tempat sebelumnya. Tetapi jika Anda menggunakan variabel tanggal untuk menghemat waktu , variabel itu tidak akan diperbarui ketika komputer beralih ke hibernasi, sehingga Anda akan tahu kapan ia keluar dari tidur dengan memeriksa variabel tanggal yang dibandingkan dengan waktu saat ini akan memiliki signifikan perbedaan dan akan lebih besar daripada interval waktu.

Menerapkan logika waktu di klien

Anda juga dapat melihat implementasi ini untuk Tanya Jawab terkait : Dapatkah browser desktop mendeteksi ketika komputer melanjutkan dari tidur?

Anda dapat mengatur timer di klien untuk berjalan setiap menit. Kami tidak akan mengandalkan interval timer , tetapi timer itu akan memeriksa variabel tanggal lingkup luar jika rentang waktu sejak timer terakhir lebih besar dari 15menit; jika ya, maka itu berarti browser / JS menghentikan eksekusi untuk beberapa alasan , mungkin hibernasi perangkat ( tidur ) dan kemudian Anda mengarahkan pengguna ke rute logout.

Contoh kode klien 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);

Anda dapat memeriksa contoh sederhana ini tetapi menggunakan 1timer kedua dengan 15logout detik di sini . Terbaik untuk mengujinya di laptop dengan menutup tutupnya dan kemudian membukanya lagi setelah 15 detik dua menit, karena jika Anda memiliki banyak program yang berjalan, komputer membutuhkan waktu untuk menghemat memori sehingga menyelesaikan mode hibernasi dan menghentikan eksekusi.

Contoh Pekerja Web

Anda bahkan dapat menggunakan API Pekerja Web untuk mengatur pekerja web agar lebih aman:

Kode JS halaman:

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.jsKode pekerja 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);

Anda juga dapat memeriksa contoh Pekerja Web dengan 15penghitung detik yang sama di sini .

Christos Lytras
sumber
Ini mengeluarkan Anda setelah 15 detik tidak peduli apa pun, tidak yakin bahwa ini yang ia cari.
Islam Elshobokshy
@IslamElshobokshy Anda benar, terima kasih atas tangkapannya. Saya lupa memperbarui clientSessionvariabel. Anda dapat memeriksa jawaban saya lagi, saya bahkan telah menambahkan contoh Pekerja Web.
Christos Lytras
Harap perbarui contoh sampel yang masih tidak berfungsi. Log pertama yang keluar setelah 15 detik tidak peduli apa. Yang kedua tidak pernah mengeluarkan Anda.
Islam Elshobokshy
@IslamElshobokshy Saya telah memperbaruinya tentu saja. Sebelumnya memiliki masalah, dan sekarang berfungsi seperti yang diharapkan. Harap perbarui halaman jika Anda belum atau mungkin menambahkan param seperti ?v=1sampai akhir.
Christos Lytras
1
Solusi Hebat + 3
AmerllicA
0

Pertama, mari kita bahas mengapa situs web Perbankan mengeluarkan Anda setelah 15 menit tanpa aktivitas. Ini persyaratan PCI untuk keamanan.

Persyaratan PCI-DSS 8.1.8 :

8.1.8 Jika suatu sesi telah diam lebih dari 15 menit, mengharuskan pengguna untuk mengautentikasi ulang untuk mengaktifkan kembali terminal atau sesi.

Untuk mencapai ini solusinya sebenarnya jauh lebih primitif daripada yang Anda bayangkan . Itu tidak memerlukan penggunaan soket web atau mengetahui apa pun tentang keadaan mesin klien (tidur atau bangun atau sebaliknya). Semua yang diperlukan adalah mengetahui waktu antara permintaan saat ini menggunakan sesi itu dan permintaan terakhir menggunakan sesi yang sama dan memastikan mereka tidak lebih dari 15 menit terpisah. Jika mereka pengguna harus diautentikasi ulang. Jika tidak, Anda dapat melanjutkan dengan permintaan.

Pesan "sesi habis"

Anda mungkin kemudian bertanya-tanya (jika sesederhana itu) bagaimana pesan batas waktu sesi muncul ketika Anda mematikan komputer dan mengaktifkannya kembali. Bagian ini tampak sederhana.

Ketika komputer dimatikan, browser benar-benar memutus semua koneksi TCP / IP yang pada gilirannya menutup loop acara di mesin javascript. Jadi timer tidak berfungsi. Tetapi ketika browser bangun lagi ia mencoba untuk menyegarkan beberapa hal termasuk halaman itu sendiri. Jadi, ketika halaman di-refresh, permintaan kembali ke server meminta server untuk meminta pengguna mengautentikasi ulang.

Namun, ini tidak akan menjelaskan modal pesan javascript (jika itu yang Anda maksud) yang dilakukan oleh beberapa situs web perbankan. Juga tidak semua browser melakukan penyegaran keras pada halaman di semua skenario. Jadi pendekatan lain bisa diambil. Daripada memiliki penghitung waktu di browser yang habis setelah 15 menit, Anda cukup menyimpan waktu pemuatan halaman dalam javascript sebagai stempel waktu dan memiliki interval waktu 1 detik yang membandingkan stempel waktu itu dengan stempel waktu komputer saat ini. Jika terpisah lebih dari 15 menit, sesi harus diakhiri.

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);


};

Bahkan jika komputer tidur dan timer berhenti, sesi akhirnya akan habis di sisi server ( lihat bagian di bawah untuk detail ) dan ketika komputer bangun lagi timer dengan interval 1 detik akhirnya akan mulai lagi, memanggil pesan (seolah-olah pengguna kehabisan waktu saat komputer sedang tidur). Waktu yang hilang antara waktu komputer pergi tidur dan waktu komputer bangun tidak masalah karena cap waktu akan tetap ada dalam memori. Putusnya sambungan antara klien dan server tidak penting karena mereka tidak perlu mengkomunikasikan informasi ini agar sesi diakhiri dengan benar di sisi server. Server dapat melakukan pengumpulan sampah sendiri dan mengakhiri sesi tanpa komunikasi dari klien (yaitu secara tidak sinkron ).

Percaya atau tidak Bank tidak peduli tentang aktivitas di dalam klien. Mereka hanya peduli tentang aktivitas permintaan ke server. Jadi jika Anda bertanya-tanya bagaimana mereka menjaga sesi tetap hidup selama lebih dari 15 menit ketika pengguna berada di halaman yang sama selama itu, mereka hanya mengirim permintaan AJAX di latar belakang untuk menyegarkan sesi setelah bertanya kepada pengguna apakah mereka masih ingin melanjutkan.

Ini bisa dilakukan dalam onloadevent callback yang sama seperti yang kita gunakan sebelumnya seperti:

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);


};

Menangani penghentian sesi di sisi server

Untuk menangani pemutusan sesi di sisi server ada beberapa pendekatan. Tergantung yang mana yang Anda gunakan, Anda akan memerlukan taktik yang berbeda. Salah satunya adalah menggunakan pengendali sesi default PHP dan pengaturansession.max_lifetime agar berakhir setelah 15 menit (ini menghapus data sesi sepenuhnya di sisi server sehingga membatalkan cookie klien).

Jika Anda membiarkan mekanisme handler sesi default melakukannya, Anda dapat mengalami masalah tergantung pada handler mana yang digunakan (file, memcached, redis, custom, dll).

Dengan file (penangan default) pengumpulan sampah terjadi dalam salah satu dari dua cara:

  • Sebagian besar sistem berbasis Debian melakukan GC sendiri melalui tugas cron (yang sangat cocok untuk skenario Anda)
  • Distro lain membiarkan PHP mekanisme GC default menanganinya, yang didasarkan pada hasil probabilistik dari setiap permintaan masuk ke PHP yang memeriksa file mtime pada file sesi dan menghapus yang melewati mereka session.max_lifetime. Masalah dengan pendekatan ini adalah bahwa pada situs dengan lalu lintas rendah sesi berpotensi duduk di sana di server untuk waktu yang lama sampai cukup banyak permintaan masuk (tergantung pada session.gc_probabilityskor) untuk memohon GC untuk membersihkan file sesi.

Dengan penangan berbasis memcached dan redis Anda tidak memiliki masalah ini. Mereka akan menangani pembersihan memori secara otomatis. Sesi mungkin masih tersimpan dalam memori fisik untuk beberapa waktu melewati masa hidup mereka, tetapi daemon tidak akan dapat mengaksesnya. Jika Anda mengkhawatirkan bit ini untuk keamanan, Anda dapat mengenkripsi sesi Anda saat istirahat atau menemukan toko kunci / nilai yang memiliki mekanisme GC pembilasan memori yang lebih ketat.

Dengan pengendali sesi khusus, Anda harus membangun mekanisme GC Anda sendiri. Melalui SessionHandlerInterfaceAnda akan menerapkan gcmetode yang memberi Anda interval seumur hidup maksimum sesi dan Anda akan bertanggung jawab untuk memverifikasi jika sesi telah melewati masa pakai berdasarkan interval ini dan melakukan pengumpulan sampah Anda dari sana.

Anda juga dapat mengatur titik akhir terpisah yang memeriksa TTL sesi (melalui permintaan AJAX asinkron di sisi klien) dan mengirimkan kembali respons jika sesi telah kedaluwarsa (memaksa javascript untuk mengautentikasi ulang pengguna).

Sherif
sumber
0

Jadi Ide ada di belakang setInterval dan Soket, setInterval didukung di sebagian besar browser dan javascript WbsocketApi didukung di hampir setiap browser.

Gambaran singkat: setInterval () - perilaku fungsi ini mengikuti saat komputer Anda dalam mode sleep / suspended / hibernate, ia dijeda dan ketika Anda berada dalam mode bangun, ia melanjutkan sendiri.

Kode berikut melakukan hal berikut, pada awalnya (mungkin pada saat yang sama tetapi) mulai php server_socket mendengarkan koneksi,

daripada javascript websocket api mengirimkan timestamp saat ini di milix detik Unix cap timestamp dalam setiap 2 detik Anda dapat memiliki 1 detik terserah Anda.

setelah itu soket server php mendapatkan waktu ini dan memeriksa apakah ia memiliki sesuatu seperti waktu sebelumnya untuk membandingkan, ketika kode pertama kali instantiated php tidak memiliki apa pun seperti waktu sebelumnya untuk membandingkannya dengan waktu yang dikirim dari javascript websocket, jadi php tidak melakukan apa-apa selain menghemat waktu ini dalam sesi yang disebut 'prev_time' dan menunggu data waktu lain yang akan diterima dari soket javascript, jadi di sini dimulai siklus kedua. ketika server php melakukan socket data waktu baru dari javascript WebsocketApi, ia memeriksa apakah ada waktu seperti waktu sebelumnya untuk membandingkan dengan data waktu yang baru diterima ini, itu berarti bahwa php memeriksa apakah ada sesi yang disebut 'prev_time', karena kami berada di siklus kedua php menemukan itu ada, meraih nilainya dan mengikuti$diff = $new_time - $prev_time, $ diff akan menjadi 2 detik atau 2000 milidetik karena ingat siklus setInterval kami terjadi dalam setiap 2 detik dan format waktu yang kami kirim dalam milidetik,

daripada memeriksa php if($diff<3000)jika perbedaannya kurang dari 3000 jika ia mengetahui bahwa pengguna aktif, sekali lagi Anda dapat memanipulasi detik ini seperti yang Anda inginkan, saya memilih 3000 karena kemungkinan latensi dalam jaringan yang hampir tidak mungkin tetapi Anda tahu saya selalu berhati-hati ketika datang ke jaringan, jadi mari kita lanjutkan, ketika php menentukan bahwa pengguna aktif php hanya me-reset sesi 'prev_time' dengan nilai $new_timeyang baru saja diterima dan hanya untuk tujuan pengujian ia mengirim pesan kembali ke soket javascript,

tetapi jika $difflebih dari 3000 itu berarti bahwa sesuatu menghentikan setInterval kami dan hanya ada cara itu bisa terjadi dan saya pikir Anda sudah tahu apa yang saya katakan, jadi dalam elselogika ( if($diff<3000)) Anda dapat logout pengguna dengan menghancurkan sesi tertentu dan jika Anda ingin mengarahkan Anda dapat mengirim beberapa teks ke soket javacript dan membuat logika yang akan dijalankan window.location = "/login"tergantung pada teks, itu dia di sini adalah kode:

Pertama adalah file index.html hanya untuk memuat javascript:

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

maka itu javascript itu tidak benar-benar kode indah tetapi Anda dapat mengetahui KOMENTAR BACA MEREKA PENTING:

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);
};

sekarang di sini adalah bagian dari kode php, jangan khawatir di bawah ada kode lengkap juga tetapi bagian ini sebenarnya apa pekerjaan yang disebutkan di atas Anda akan memenuhi fungsi-fungsi lain juga, tetapi mereka untuk decoding dan bekerja dengan soket javascript sehingga hal yang sebenarnya benar di sini BACA KOMENTAR MEREKA PENTING:

<?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);

?>

Dan di sini adalah kode lengkap dari 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;
}

CATATAN BACA TI: $new_timevariabel $jsTimedalam Kode

buat folder dan cukup salin dan tempel ini dalam file yang menjalankan soket php dengan perintah: php -f server_socket.php pergi ke localhost dan mengujinya konsol terbuka untuk melihat pesan itu akan mengatakan "Anda aktif" atau "Anda tidak aktif" (ketika Anda datang dari tidur); executin Anda akan terjadi ketika pengguna akan datang dari tidur bukan ketika mereka tidur karena pada saat itu semuanya di-cache di pagefile (windows) atau di swap (linux)

Dato DT
sumber
buat folder dan cukup salin dan tempel ini dalam file yang menjalankan soket php dengan perintah: php -f server_socket.php pergi ke localhost dan mengujinya konsol terbuka untuk melihat pesan itu akan mengatakan "Anda aktif" atau "Anda tidak aktif" (ketika Anda datang dari tidur); executin Anda akan terjadi ketika pengguna akan datang dari tidur bukan ketika mereka tidur karena pada saat itu semuanya di-cache di pagefile (windows) atau di swap (linux)
Dato DT
0

Saya pikir saya punya ide, Anda telah banyak membahas tentang cara kerja sistem masuk / keluar bank.

Kasus-1: Akses halaman web ke pengguna untuk waktu yang tidak terbatas jika pengguna aktif

Setiap kali pengguna masuk, Mulai timer di backend Anda (atur batas waktu apa pun yang Anda inginkan), misalkan 15 menit. Sekarang apa artinya ?? Ini berarti jika pengguna tidak melakukan aktivitas apa pun di halaman web, maka kami akan mengeluarkannya.

Sekarang, dari depan Anda dapat mengirim aktivitas pengguna ke backend Anda (bisa mengirim menggunakan soket atau polling panjang), yang pada dasarnya akan mengatur ulang timer dan pengguna dapat menggunakan halaman web secara aktif untuk waktu kapan pun mereka inginkan.

Jika pengguna mematikan PC, timer tidak akan direset dan Anda dapat membatalkan sesi begitu timer berakhir.

Jika Anda ingin membatalkan sesi pengguna begitu mereka mengaktifkan komputernya, Anda dapat menetapkan batas waktu sesi untuk memvalidasi. Misalnya, saat pengguna masuk, kami akan membuat sesi yang hanya berlaku selama 10 detik, dan setelah kami menerima permintaan aktivitas pengguna, kami dapat mengatur ulang penghitung waktu dan memberikan kunci sesi baru.

Saya harap ini membantu Anda. Beri tahu saya jika Anda memiliki pertanyaan.

Harsh Srivastava
sumber
-1

Saya menulis sebuah skrip untuk mendeteksi jika mesin tidur. Gagasannya adalah bahwa ketika mesin dalam mood tidur semua skrip akan berhenti. Karena itu jika kita melacak waktu saat ini dalam interval waktu. Setiap kaliInterval memicu waktu saat ini dikurangi (-) waktu baru harus cukup dekat dengan timeInterval. Karenanya jika kita ingin memeriksa apakah timer idle untuk X time, kita dapat memeriksa apakah perbedaan waktu lebih dari X.

Contoh memeriksa pukulan jika komputer ditidurkan selama lebih dari 15-an. Harap dicatat ketika Anda mematikan komputer, perlu waktu 15 detik tambahan untuk mengetahui semua prosesor. (Saat diuji pada 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.');
	}
});

Lasithds
sumber
Tolong jelaskan mengapa ini tidak akan berhasil, jika tidak dalam kasus Anda
Lasithds
-1

Saya telah menerapkan persyaratan yang sama persis dengan menggunakan AWS Cognito, dengan Lambda Authorizers, & Redis, saya tidak dapat membagikan kode pada tahap ini, tetapi saya dapat memberi tahu Anda semua bagaimana penerapannya dengan komponen-komponen ini, konsep yang sama dapat digunakan dengan yang lain komponen bukan AWS.

Pertama dengan menerapkan logout tidak aktif, Anda harus melakukannya di sisi server, seolah-olah seseorang mematikan komputer mereka, situs web front-end tidak akan logout. Saya menggunakan konsep ACTIVEpengguna. Ketika pengguna berhasil mengotentikasi, saya menyimpan dengan TTL 15 menit di Redis entri dengan kunci username& nilai mereka ACTIVE(itu bisa menjadi nama pengguna + sessionid jika Anda ingin memperbolehkan beberapa sesi untuk pengguna yang diberikan pada waktu yang sama).

Di Authorizers khusus saya ketika pengguna ACTIVE& mereka memiliki Token yang valid, saya memberi mereka akses ke sumber daya yang dilindungi DAN yang paling penting, saya melakukan yang lain menempatkan Redis dengan username& ACTIVE.

Setiap kali pengguna logout, saya logout di solusi manajemen identitas saya (Cognito) & saya menandainya sebagai INACTIVE. Perhatikan bahwa jika pengguna tidak mencapai API dalam waktu 15 menit mereka tidak akan lagi memiliki entri ACTIVEterhadap nama pengguna mereka dan tidak akan dapat mengakses API lagi & harus masuk lagi, untuk itu mereka akan diarahkan kembali untuk melakukannya.

Ada banyak hal yang perlu dipertimbangkan dengan pendekatan ini, untuk satu hal yang sering otorisasi membuat cache hasil untuk beberapa waktu, dan jika katakan Anda men-cache hasil selama 5 menit sebagai contoh, maka pengguna Anda mungkin logout dalam 10 menit sebagai pengguna Anda bisa menekan cache alih-alih Authorizer yang tidak akan menyegarkan ACTIVEentri.

Penting juga bahwa Anda memastikan apa pun yang Anda gunakan untuk menyimpan jika pengguna tertentu ACTIVEsangat tersedia dan akan pulih dengan cepat jika terjadi kegagalan.

Pendekatan menggunakan cache store dengan cara ini mirip dengan bagaimana token invalidation dipasang pada protokol otorisasi stateless seperti OAuth2.

Kami telah menggunakan pendekatan ini selama beberapa bulan sekarang, tampaknya berfungsi dengan baik bagi kami, itu bisa menjadi persyaratan yang menjengkelkan untuk ditangani, saya telah berharap di dunia AWS bahwa akan ada yang siap untuk digunakan solusi kotak untuk ini tetapi tidak ada yang bisa dibicarakan.

Snickers3192
sumber
Kami juga selamat dari tes pena (; Di sinilah persyaratan kami berasal dari awalnya, aplikasi kami adalah produk berbasis layanan keuangan, dan kami harus menerapkan ini sebagai persyaratan.
Snickers3192