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?
sumber
Jawaban:
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 mulailaravel-websockets
dari 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 denganpusher
protokol. 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 untuklaravel-websockets
server seperti masalah github ini "Ada cara untuk mengimplementasikan webhooks? " .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
15
menit; 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:
Anda dapat memeriksa contoh sederhana ini tetapi menggunakan. Terbaik untuk mengujinya di laptop dengan menutup tutupnya dan kemudian membukanya lagi setelah1
timer kedua dengan15
logout detik di sini15 detikdua 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:
logoutWorker.js
Kode pekerja web :Anda juga dapat memeriksa contoh Pekerja Web dengan
15
penghitung detik yang sama di sini .sumber
clientSession
variabel. Anda dapat memeriksa jawaban saya lagi, saya bahkan telah menambahkan contoh Pekerja Web.?v=1
sampai akhir.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 :
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.
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
onload
event callback yang sama seperti yang kita gunakan sebelumnya seperti: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 pengaturan
session.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:
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 padasession.gc_probability
skor) 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
SessionHandlerInterface
Anda akan menerapkangc
metode 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).
sumber
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_time
yang baru saja diterima dan hanya untuk tujuan pengujian ia mengirim pesan kembali ke soket javascript,tetapi jika
$diff
lebih 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 dalamelse
logika (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 dijalankanwindow.location = "/login"
tergantung pada teks, itu dia di sini adalah kode:Pertama adalah file index.html hanya untuk memuat javascript:
maka itu javascript itu tidak benar-benar kode indah tetapi Anda dapat mengetahui KOMENTAR BACA MEREKA PENTING:
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:
Dan di sini adalah kode lengkap dari php:
CATATAN BACA TI:
$new_time
variabel$jsTime
dalam Kodebuat 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)
sumber
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.
sumber
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).
sumber
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
ACTIVE
pengguna. Ketika pengguna berhasil mengotentikasi, saya menyimpan dengan TTL 15 menit di Redis entri dengan kunciusername
& nilai merekaACTIVE
(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 denganusername
&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 entriACTIVE
terhadap 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
ACTIVE
entri.Penting juga bahwa Anda memastikan apa pun yang Anda gunakan untuk menyimpan jika pengguna tertentu
ACTIVE
sangat 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.
sumber