Bilgisayarını uyku moduna geçirdiğinde bir kullanıcının web sitesinden çıkış yapması


11

Bu tuhaf biri. Bir Laravel web sitemiz var ve bu sitede kullanıcı başına bir zamanlayıcı var, burada önyüklenmeden önce 15 dakika aktif olmuyorlar.

Bunu, bir tepki bileşenindeki sayfada oturan bir zamanlayıcı ile yapıyoruz, istediğimiz gibi çalışıyor, ancak şimdi yeni bir sorun var: Bir kullanıcı oturum açıp dizüstü bilgisayarlarının kapağını kapatırsa web sitesi önyükleme yapmalıdır . Bankalar bunu yapar, Okullar ve Üniversiteler bunu yapar, Hükümet siteleri de bunu yapar. Yani mümkün, sadece nasıl emin değilim.

Laravel-websockets kütüphanesi ve Yankı kullanarak web soketleri kullanıyoruz . Ne görmek istiyorum:

  • Dizüstü bilgisayarınızı kapattığınızda giriş ekranına önyükleme yapın. Dizüstü bilgisayarı bir sonraki açışınızda ve giriş yaptığınızda ve tarayıcıyı giriş ekranında gördüğünüzde. Bu kadar hızlı olmak zorunda değil, ancak ön tarafa temelde sayfayı yenilemelerini söyleyen bir şey göndermenin bir yoluna ihtiyacımız var, oturum öldürüldükten sonra, oturum ömrünü 15 dakikalık bir süreye ayarladık.

Bazı insanlar diğer benzer sorularda öneride bulundu:

  • web soketi işleyicisi nasıl oluşturulur
  • Oturum çerezini (tarayıcıda) arka uçtaki kullanıcı çereziyle karşılaştırmak için.
  • Ön uçta çalışan bir zamanlayıcı için (bunu yaparız, dizüstü bilgisayarın kapağını kapattığınızda durur)

En popüler olanı, web soketlerini kullanıyor, kullanıcının bağlantılarını kesip sonra önyüklemesini dinliyor gibi görünüyor, ki bu iyi ve hepsi, ama sonra onları önyüklemek için askıya alınan bir tarayıcıya nasıl istek gönderirsiniz?

RequestIdleCallback () buldum Ama yine de, ben zaten sitede bir kalp atışı zamanlayıcı varsa ne istediğimi sanmıyorum. Ayrıca tüm tarayıcılarda çalışmaz.

Burada bunu nasıl yapacağım konusunda çok kayboldum, verebileceğim örnek:

Bankanıza giriş yapın, bilgisayarınızı uyku moduna geçirin, 15-20 dakika bekleyin, bilgisayarı uyandırın, giriş yapın ve bankanızın oturum açma ekranında sizi gördüğünü görün. İstediğim bu . Ama bunu nasıl başaracağımı bilmiyorum.

Arka uçtan bir "uyku" tarayıcısına olay gönderemezsiniz ve evet bu bir arka uç çözümü olmak zorundayken, dizüstü bilgisayarı yeniden uyandırdıklarında çıkış ekranında olmaları için ön uç nasıl güncellenir? veya bilgisayar?


7
Sadece oturum cooke son kullanma tarihini "now + 15 minutes" olarak ayarlayın ... yine de son ekranı görebiliyor olsanız da, çerezin süresi dolmuşsa bu oturumda işlem yapamazsınız. Ve "giriş ekranına önyükleme" - Belirli bir süre işlem yapılmadığında bir bilgisayarı otomatik olarak kapatacak bir işletim sistemi ayarı olduğundan eminim ..
Lars Stegelitz

1
Bir site yüklendiğinde, oturum çerezinizle aynı zaman aşımına sahip bir Javascript zamanlayıcı başlatabilirsiniz ... zamanlayıcı "çalarsa", kullanıcı çok uzun süre hareketsiz kalır. Sonra oturumu kapatırsınız (AJAX çağrısı) ve tarayıcıyı giriş ekranına veya "özür dileriz, hareketsizlik nedeniyle oturumu
kapattık

1
Tamam ben yaptım cevap şimdi ekliyorum.
Dato DT

1
bu işe yaradı mı?
Dato DT

1
@DatoDT Hayır, Bir ben laravel kullanıyorum, iki zaten açılış mesajımda ifade edilen laravel soketlerini kullanıyorum, iki kodunuz çok dağınık, OOP değil, test edilmedi ve asla kullanmam. Aslında bir laravel çözümü arıyorum.
TheWebs

Yanıtlar:


0

GÜNCELLEME

WebSocket isteğiyle ilgili olarak, Laravel WebSockets ile birlikte kullandığınızı varsayıyorum pusher. Pusher.io zaman aşımını desteklemiyorsa , "Kanallar itici-js istemci kitaplığına bir bağlantı zaman aşımı özelliği eklemeyi planlıyor musunuz?" . Laravel hata ayıklama modunu ( APP_DEBUG=true içeride .env ) etkinleştirirseniz ve çıkış günlüğü olaylarını görebilmek için laravel-websocketsterminalden ( php artisan websockets:serve) başlarsanız test edebilirsiniz. Dizüstü bilgisayarın kapağını kapatmaya veya bilgisayarı hazırda bekletme moduna ( uyku ) ayarlarsanız, bu olayla ilgili herhangi bir ileti görmezsiniz. pusherProtokol ile yapamazsınız . Orada varlığı olaymember_removed , ancak yalnızca sekmeyi kapattığınızda veya oturumu kapattığınızda tetiklenir. Tabii ki istemcinizin özel etkinliğini iletişim kanalına tetikleyebilirsiniz, ancak bunu yapmak için istemci tarafında bir zamanlayıcı kurulumuna da ihtiyacınız vardır ve laravel-websocketssunucu için bu github sorunu gibi bir hizmet sağlayıcı oluşturmanız gerekir . webhooks uygulamak? " .

Bazı insanlar diğer benzer sorularda öneride bulundu:

...

  • Ön uçta çalışan bir zamanlayıcı için ( bunu yaparız, dizüstü bilgisayarın kapağını kapattığınızda durur )

Bunun nedeni, istemci zamanlayıcıların hazırda bekletme modundaki yürütmeyi durdurmasıdır, böylece daha önce bulundukları yerden devam ederler. Ancak zamandan tasarruf etmek için bir tarih değişkeni kullanırsanız, bilgisayar hazırda bekletme moduna geçtiğinde bu değişken güncellenmez, böylece geçerli zamanla karşılaştırıldığında önemli olan tarih değişkenini kontrol ederek uykudan ne zaman çıkacağını bilirsiniz. fark ve zamanlayıcı aralığından daha büyük olacaktır.

İstemcide zaman mantığını uygulama

Bu uygulamayı bu S / C için de görebilirsiniz : Bilgisayar uyku modundan çıktığında herhangi bir masaüstü tarayıcı algılayabilir mi?

İstemcide her dakikayı çalıştırmak için bir zamanlayıcı ayarlayabilirsiniz. Zamanlayıcı aralığına güvenmeyiz , ancak bunun yerine, son zamanlayıcıdan bu yana geçen süre dakikadan büyükse , zamanlayıcı bir dış kapsam tarih değişkenini kontrol edecektir 15; öyleyse, bu , tarayıcının / JS'nin herhangi bir nedenle yürütmeyi durdurduğu , muhtemelen cihazın hazırda bekletilmesi ( uyku ) anlamına gelir ve daha sonra kullanıcıyı oturum kapatma yoluna yönlendirirsiniz.

Örnek JS istemci kodu:

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

Bu basit örneği kontrol edebilirsiniz, ancak burada oturum kapatılan saniye sayacıyla 1ikinci zamanlayıcıyı kullanabilirsiniz15 . En iyisi, kapağı kapatarak bir dizüstü bilgisayarda test etmek ve ardından iki saniyede 15 saniye sonra tekrar açmaktır , çünkü çok sayıda programınız varsa, bilgisayarın bellek durumunu kaydetmesi biraz zaman alır, böylece hazırda bekletme modunu tamamlar ve yürütmeyi durdurur.

Web Çalışanları Örneği

Bir web çalışanını çok daha güvenli olacak şekilde ayarlamak için Web Workers API'sını bile kullanabilirsiniz :

Sayfa JS kodu:

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

Web çalışan logoutWorker.jskodu:

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

Web Çalışanı örneğini burada aynı 15saniye zamanlayıcısıyla da kontrol edebilirsiniz .


Bu ne olursa olsun, 15 saniye sonra oturumunuzu kapatır, aradığı şeyin bu olduğundan emin değilsiniz.
İslam Elshobokshy

@IslamElshobokshy haklısın, yakaladığın için teşekkürler. clientSessionDeğişkeni güncellemeyi unuttum . Cevabımı tekrar kontrol edebilirsiniz, bir Web Çalışanı örneği bile ekledim.
Christos Lytras

Lütfen hala çalışmayan örnek örnekleri güncelleyin. İlki, 15 saniye sonra ne olursa olsun oturumunuzu kapatır. İkincisi asla oturumunuzu kapatmaz.
İslam Elshobokshy

@IslamElshobokshy Elbette güncelledim. Önce bir sorun vardı ve şimdi beklendiği gibi çalışıyor. Sonuna benzer bir parametre eklemediyseniz veya belki eklemediyseniz lütfen sayfayı ?v=1yeniden düzenleyin.
Christos Lytras

1
Great Solution + 3
AmerllicA

0

İlk olarak, Bankacılık web sitelerinin neden etkinlik yapmadan 15 dakika sonra oturumunuzu kapattığına bakalım. Güvenlik için bir PCI gereksinimi.

PCI-DSS gereksinimi 8.1.8 :

8.1.8 Bir oturum 15 dakikadan uzun bir süredir boşta kalırsa, terminali veya oturumu yeniden etkinleştirmek için kullanıcının yeniden kimlik doğrulaması yapmasını isteyin.

Bunu başarmak için çözüm aslında hayal ettiğinden çok daha ilkeldir . Ne websockets kullanımı ne de müşterinin makinesinin durumu (uyku veya uyanık veya başka türlü) hakkında bir şey bilmeyi gerektirmez. Gerekli olan tek şey, o oturumu kullanan mevcut istek ile aynı oturumu kullanan son istek arasındaki zamanı bilmek ve aralarının 15 dakikadan fazla olmamasını sağlamaktır. Eğer öyleyse, kullanıcının yeniden doğrulanması gerekir. Eğer değilse, talebe devam edebilirsiniz.

"Oturum zaman aşımına uğradı" mesajı

Muhtemelen (eğer bu kadar basitse) bilgisayarı uyku moduna sokup yeniden uyandırdığınızda oturum zaman aşımına uğramış mesajının nasıl göründüğünü merak ediyorsunuzdur. Bu bölüm aldatıcı bir şekilde basit.

Bilgisayar uyku moduna alındığında, tarayıcı tüm TCP / IP bağlantılarını keser ve bu da javascript motorundaki olay döngüsünü kapatır. Yani zamanlayıcılar çalışmıyor. Ancak tarayıcı tekrar uyandığında sayfanın kendisi de dahil olmak üzere bazı şeyleri yenilemeye çalışır. Böylece sayfa yenilendiğinde, istek, kullanıcının yeniden kimlik doğrulaması yapmasını istemek için sunucuyu çağıran sunucuya geri döner.

Ancak, bu, bazı bankacılık web sitelerinin yaptığı javascript mesaj modunu (bahsettiğiniz şey buysa) hesaba katmaz. Ayrıca, tüm tarayıcılar tüm senaryolarda sayfada sert bir yenileme yapmaz. Böylece başka bir yaklaşım benimsenebilir. Tarayıcıda 15 dakika sonra zaman aşımına uğrayan bir zamanlayıcıya sahip olmak yerine, sayfa yükleme süresini javascript'te zaman damgası olarak saklayabilir ve bu zaman damgasını bilgisayarın geçerli zaman damgasıyla karşılaştıran 1 saniyelik bir zaman aşımı süresine sahip olabilirsiniz. 15 dakikadan daha uzun aralıklarla oturumlar sonlandırılmalıdır.

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


};

Bilgisayar uyku moduna geçse ve zamanlayıcı dursa bile, oturum sonunda sunucu tarafında zaman aşımına uğrayacaktır ( ayrıntılar için aşağıdaki bölüme bakın ) ve bilgisayar tekrar uyandığında 1 saniyelik aralıkla zamanlayıcı tekrar başlatılır ve mesajı (bilgisayar uykudayken zaman aşımına uğramış gibi). Bilgisayarın uyku moduna geçtiği zaman ile bilgisayarın uyanma zamanı arasında kaybedilen zaman, zaman damgası bellekte kalacağı için önemli değildir. İstemci ile sunucu arasındaki bağlantı önemsizdir, çünkü oturumun sunucu tarafında düzgün bir şekilde sonlandırılması için bu bilgileri iletmeleri gerekmez. Sunucu kendi çöp toplama işlemini yapabilir ve istemciden (örn. Eşzamansız olarak ) iletişim kurmadan oturumu sonlandırabilir .

İster inanın ister inanmayın Bankalar müşterinin içindeki faaliyetleri önemsemez. Yalnızca sunucuya istek etkinliğini önemsiyorlar. Bu nedenle, kullanıcı aynı sayfada uzun süre oturduğunda oturumu 15 dakikadan daha uzun süre nasıl canlı tuttuğunu merak ediyorsanız, kullanıcıya arka planda hala bir AJAX isteği göndererek kullanıcıya hâlâ olup olmadığını sorar. devam etmek istiyorum.

Bu, onloaddaha önce kullandığımız aynı olay geri aramasında şu şekilde yapılabilir :

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


};

Sunucu tarafında oturum sonlandırmayı yönetme

Sunucu tarafında oturum sonlandırma işlemek için birkaç yaklaşım vardır. Hangisini kullandığınıza bağlı olarak farklı taktiklere ihtiyacınız olacak. Biri PHP'nin varsayılan oturum işleyicisini kullanıyor ve session.max_lifetime15 dakika sonra süresi dolacak şekilde ayarlıyor (bu, oturum verilerini tamamen sunucu tarafında siler ve böylece istemcinin çerezini geçersiz kılar).

Varsayılan oturum işleyici mekanizmasının yapmasına izin verirseniz, hangi işleyicinin kullanıldığına (dosyalar, memcached, redis, özel, vb.) Bağlı olarak sorunlarla karşılaşabilirsiniz.

Dosyalarla (varsayılan işleyici) çöp toplama iki yoldan biriyle gerçekleşir:

  • Çoğu Debian tabanlı sistem bir cron işi aracılığıyla kendi GC'lerini yapar (bu sizin senaryo için harika çalışır)
  • Diğer dağıtımlar, PHP'nin varsayılan GC mekanizmasının, oturum dosyalarındaki dosya mtime'larını kontrol eden ve geçmiş olanları silen PHP'ye gelen her isteğe bağlı bir sonuca dayanan, işlemesine izin verir session.max_lifetime. Bu yaklaşımla ilgili sorun, düşük trafikli sitelerde bir oturumun session.gc_probability, oturum dosyalarını temizlemek için GC'yi çağırmak için yeterli sayıda istek gelene kadar ( puana bağlı olarak ) sunucuda potansiyel olarak uzun süre oturabilmesidir .

Memcached ve redis tabanlı işleyicilerde bu sorunla karşılaşmazsınız. Hafızayı otomatik olarak temizlemeyi üstlenirler. Oturumlar, ömürleri boyunca bir süre daha fiziksel bellekte kalabilir, ancak arka plan programı onlara erişemez. Güvenlik için bu bit konusunda endişeleriniz varsa, oturumlarınızı istirahatte şifreleyebilir veya daha katı bellek temizleme GC mekanizması olan bir anahtar / değer deposu bulabilirsiniz.

Özel bir oturum işleyicisi ile kendi GC mekanizmanızı oluşturmanız gerekecektir. Aracılığıyla SessionHandlerInterfacebir uygulamaya ediyorum gcyöntemi olduğunu eli oturumun maksimum ömür boyu aralığı ve oturumu bu aralığa göre ömrünü geçtiyse doğrulanması sorumlu olacak ve oradan çöp toplama yapardım.

Ayrıca, oturum TTL'sini (istemci tarafında eşzamansız AJAX isteği aracılığıyla) kontrol eden ve oturumun süresi dolduysa (javascript'in kullanıcıyı yeniden kimlik doğrulaması yapmaya zorlayarak) bir yanıt gönderen ayrı bir bitiş noktası da ayarlayabilirsiniz.


0

Fikir setInterval ve Sockets'in arkasındadır, setInterval çoğu tarayıcıda desteklenir ve Javascript WbsocketApi hemen hemen her tarayıcıda desteklenir.

Kısa genel bakış: setInterval () - Bu işlev davranışı, bilgisayarınız uyku / askıya alınmış / hazırda bekletme modundayken duraklatılır ve uyanma modundayken kendini devam ettirir.

Aşağıdaki kod ilk önce (belki de aynı zamanda ama) aşağıdakileri yapar, bağlantıları dinlemeye php server_socket başlatır,

javascript websocket api, Unix zaman damgası milisaniye cinsinden geçerli zaman damgasını her 2 saniyede gönderir, size 1 saniye sürebilir.

Bundan sonra php sunucu soketi bu kez alıyor ve karşılaştırmak için önceki zaman gibi bir şey olup olmadığını kontrol eder, kod ilk örneklendiğinde php javascript websocket gönderilen zamanla karşılaştırmak için önceki zaman gibi bir şey yok, bu yüzden php "prev_time" adlı oturumda bu kez kaydedilen hiçbir şey yapmaz ve javascript soketinden başka bir zaman verisinin alınmasını bekler, dolayısıyla burada ikinci döngü başlar. php sunucu soketi javascript WebsocketApi'den yeni zaman verileri sokulduğunda, bu yeni alınan zaman verileri ile karşılaştırmak için önceki zamana benzer bir şey olup olmadığını kontrol eder, php, 'prev_time' adı verilen oturumun var olup olmadığını kontrol eder, çünkü ikinci döngüde php, var, değerini alıyor ve takip ediyor$diff = $new_time - $prev_time, $ diff 2 saniye veya 2000 milisaniye olacaktır çünkü setInterval döngümüzün her 2 saniyede bir gerçekleştiğini ve gönderdiğimiz zaman biçiminin milisaniye olduğunu unutmayın,

php if($diff<3000), kullanıcının aktif olduğunu biliyorsa farkın 3000'den az olup olmadığını kontrol eder , yine bu saniyeleri istediğiniz gibi manipüle edebilirsiniz, 3000'i seçiyorum çünkü ağda neredeyse imkansız olan olası gecikme, ancak her zaman dikkatli olduğumu biliyorsunuz bu ağlara gelir, bu yüzden php kullanıcının aktif olduğunu belirlediğinde php sadece $new_timeyeni alınan değeri ile 'prev_time' oturumunu sıfırlar ve sadece test amacıyla javascript soketine mesaj gönderir,

ancak $diff3000'den fazla ise, bir şey setInterval'ı duraklattı demektir ve bunun tek yolu olabilir ve bence ne dediğimi zaten biliyorsunuzdur, bu nedenle else( if($diff<3000)) mantığında, belirli oturumu yok ederek kullanıcıyı kapatabilirsiniz ve yeniden yönlendirmek istiyorsanız, javacript soketine bazı metinler gönderebilir window.location = "/login"ve metne bağlı olarak yürütülecek bir mantık oluşturabilirsiniz , işte burada kod:

İlk olarak sadece javascript yüklemek için index.html dosyasıdır:

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

o zaman gerçekten güzel bir şekilde kodlanmamış bir javascripttir, ancak ÖNEMLİ OLDUĞU YORUMLARI okuyabilirsiniz:

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

şimdi burada php kodunun bir parçası, endişelenmeyin aşağı tam kod da var ama bu kısım aslında yukarıda belirtilen işleri de diğer işlevleri karşılayacak ama onlar çözme ve javascript yuvaları ile çalışmak için bu yüzden gerçek bir şey doğru burada ÖNEMLİ YORUMLARI OKUYUN:

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

?>

Ve burada php tam kodu:

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

NOT IT READ: $new_timedeğişken $jsTimeKodda

klasör oluşturmak ve sadece kopyalayıp yapıştırın php soket komut ile dosyaları yapıştırın: php -f server_socket.php localhost gidin ve "aktif" veya "aktif değil" diyecek mesajları görmek için konsolu açık test (uykudan geldiğinizde); uygulamanız kullanıcı uyku modundayken değil uykudan geldiğinde gerçekleşecektir, çünkü o anda her şey pagefile (windows) veya swap (linux) içinde önbelleğe alınır


klasör oluşturmak ve sadece kopyalayıp yapıştırın php soket komut ile dosyaları yapıştırın: php -f server_socket.php localhost gidin ve "aktif" veya "aktif değil" diyecek mesajları görmek için konsolu açık test (uykudan geldiğinizde); uygulamanız kullanıcı uyku modundayken değil uykudan geldiğinde gerçekleşecektir, çünkü o anda her şey sayfa dosyasında (windows) veya takasta (linux) önbelleğe alınır
Dato DT

0

Sanırım bir fikrim var, banka giriş / çıkış sisteminin nasıl çalıştığı hakkında çok konuştunuz.

Durum-1: Kullanıcı aktifse web sayfasının kullanıcıya sınırsız süreyle erişimi

Kullanıcı her oturum açtığında, arka ucunuzda bir zamanlayıcı başlatın (istediğiniz zaman sınırını ayarlayın), diyelim ki 15 dakika. Şimdi ne anlama geliyor ?? Bu, kullanıcı web sayfasında herhangi bir etkinlik gerçekleştirmezse, oturumunu kapatacağımız anlamına gelir.

Şimdi önden kullanıcı etkinliğini arka ucunuza gönderebilirsiniz (soket veya uzun yoklama kullanarak gönderilebilir), bu temelde zamanlayıcıyı sıfırlar ve kullanıcı web sayfasını istedikleri zaman aktif olarak kullanabilir.

Kullanıcı bilgisayarını uyku moduna geçirirse, zamanlayıcı sıfırlanmaz ve zamanlayıcı sona erdiğinde oturumu geçersiz kılabilirsiniz.

Bilgisayarı uyku moduna geçirir koymaz kullanıcı oturumunu geçersiz kılmak istiyorsanız, oturumun geçerlilik süresinin sınırını ayarlayabilirsiniz. Örneğin, kullanıcı oturum açtığında, yalnızca 10 saniye boyunca geçerli olacak oturumu oluşturacağız ve kullanıcı etkinliği isteğini aldıktan sonra zamanlayıcıyı sıfırlayabilir ve yeni bir oturum anahtarı sağlayabiliriz.

Umarım bu sana yardımcı olur. Herhangi bir sorunuz varsa bana bildirin.


-1

Makinenin uyku moduna geçip geçmediğini tespit etmek için bir senaryo yazdım. Fikir, makine uyku modundayken tüm komut dosyalarının duracağıdır. Bu nedenle, bir zaman içinde geçerli saati takip edersek Interval. TimeInterval, geçerli saati eksi (-) her tetiklediğinde, yeni zamanın timeInterval'e yeterince yakın olması gerekir. Bu nedenle, zamanlayıcının X zamanı için boşta olup olmadığını kontrol etmek istiyorsak, zaman farkının X'den fazla olup olmadığını kontrol edebiliriz.

Örnek darbe, bilgisayarın 15 saniyeden uzun bir süre uyku moduna geçip geçmediğini kontrol eder. Bilgisayarı uyku moduna geçirdiğinizde, tüm işlemcileri düşünmek için fazladan 15 saniye sürdüğünü lütfen unutmayın. (MY PC'de test edildiğinde).

(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.');
	}
});


Eğer durumunuzda değilse, bunun neden işe yaramayacağını lütfen açıklayın
Lasithds

-1

Aynı gereksinimi AWS Cognito'yu kullanarak Lambda Yetkilendiricileri ve Redis ile uyguladım, bu aşamada kodu paylaşamıyorum, ancak bu bileşenlerle nasıl uygulandığını her şeyi söyleyebilirim, aynı kavramlar diğerleriyle kullanılabilir AWS olmayan bileşenler.

Öncelikle bir hareketsizlik oturumu kapatma uygulamasıyla, sunucu tarafını yapmak zorunda kalacaksınız, sanki birileri bilgisayarlarını kapatıyormuş gibi, ön uç web sitesi bunları kapatmaz. ACTIVEKullanıcı kavramını kullandım . Kullanıcılar başarılı bir şekilde kimlik doğrulaması yaptığında, Redis'te 15 dakikalık bir TTL ile kendi anahtarları ve usernamedeğeri olan bir girişle depolarım ACTIVE(aynı anda birden fazla oturuma izin vermek istiyorsanız kullanıcı adı + oturum kimliği olabilir).

Bir kullanıcı olduğunda ACTIVEve geçerli bir Jetonu olduğunda özel Yetkilendiricilerimde , korunan kaynağa erişmelerine izin veriyorum ve en önemlisi, Redis'te username& ile bir başka koyma yapıyorum ACTIVE.

Kullanıcı oturumu kapattığında, kimlik yönetimi çözümümde (Cognito) oturumumu kapatırım ve olarak işaretlerim INACTIVE. Bir kullanıcı 15 dakika içinde API'ya ulaşmazsa, artık ACTIVEkullanıcı adına karşı bir girişi olmayacak ve API'ya artık erişemeyeceğini ve yeniden yönlendirilmek üzere tekrar oturum açmaları gerekmeyeceğini unutmayın.

Bu yaklaşımla göz önünde bulundurulması gereken birçok şey vardır, çünkü bir şey genellikle Yetkilendiriciler sonuçları bir süre önbelleğe alır ve sonucu örnek olarak 5 dakika önbellekte saklarsanız, kullanıcı olarak kullanıcı 10 dakika içinde oturumu kapatmış olabilir ACTIVEgirdiyi yenilemeyen Yetkilendirici yerine önbelleğe çarpabilir .

Ayrıca, belirli bir kullanıcı ACTIVEyüksek oranda kullanılabilir olduğunda ve bir arıza durumunda hızlı bir şekilde kurtarılacaksa, depolamak için kullandığınız her şeyi kullandığınızdan emin olmanız önemlidir .

Bu şekilde bir önbellek deposu kullanma yaklaşımı, token geçersiz kılmanın OAuth2 gibi durum bilgisi olmayan yetkilendirme protokollerine nasıl uyarlandığına benzer.

Bu yaklaşımı birkaç aydır kullanıyoruz, bizim için iyi çalışıyor gibi görünüyor, üstesinden gelmek biraz can sıkıcı bir gereklilik olabilir, AWS dünyasında kullanıma hazır olacağını umuyordum Bunun için konuşacak bir çözüm yoktu.


Ayrıca bir kalem testinden de kurtulduk (; Bu bizim gereksinimimiz başlangıçta geldi, başvurumuz finansal hizmetler tabanlı bir üründür ve bunu bir gereklilik olarak uygulamak zorunda kaldık.
Snickers3192
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.