컴퓨터를 절전 모드로 전환 할 때 웹 사이트에서 로그 아웃


11

이것은 기괴한 것입니다. 우리는 라 라벨 웹 사이트를 가지고 있으며, 사이트에는 사용자 당 타이머가 있으며, 부팅하기 전에 15 분 동안 활동하지 않습니다.

우리는 반응 구성 요소의 페이지에있는 타이머를 통해이 작업을 수행하지만 원하는대로 작동하지만 이제는 새로운 문제가 있습니다. 사용자가 로그인하여 랩톱의 뚜껑을 닫으면 웹 사이트에서 부팅해야합니다 . 은행은 이것을하고 학교와 대학은 이것을하고 정부 기관은 이것을합니다. 방법이 확실하지 않습니다.

우리는 laravel-websockets 라이브러리와 Echo를 사용하여 웹 소켓을 사용 합니다. 내가보고 싶은 것은 :

  • 랩톱을 닫으면 로그인 화면으로 부팅됩니다. 다음에 랩탑을 열고 로그인하면 로그인 화면에 브라우저가 표시됩니다. 그렇게 빨리 일어날 필요는 없지만 기본적으로 페이지를 새로 고치라고 알리는 무언가를 프런트 엔드에 보내는 방법이 필요합니다. 세션이 종료되면 세션 수명을 15 분의 laravel로 설정합니다.

어떤 사람들은 다른 비슷한 질문을 제안했습니다.

가장 인기있는 것은 웹 소켓을 사용하는 것 같습니다. 사용자가 연결을 끊었다가 부팅하는 것을 듣는 것은 괜찮습니다.하지만 일시 중지 된 브라우저에 요청을 보내서 부팅하는 방법은 무엇입니까?

requestIdleCallback () 을 찾았 지만 다시 사이트에 이미 하트 비트 타이머가 있으면 이것이 내가 원하는 것이라고 생각하지 않습니다. 모든 브라우저에서 작동하지는 않습니다.

나는 이것을 달성하는 방법에 대해 여기서 잃어 버렸습니다. 내가 줄 수있는 예는 다음과 같습니다.

은행에 로그인하고 컴퓨터를 잠자기 상태로두고 15-20 분 정도 기다린 후 컴퓨터를 깨우고 로그인하여 은행에 로그인 화면이 표시됩니다. 그것이 내가 원하는 것 입니다. 그러나 나는 그것을 달성하는 방법을 모른다.

백엔드에서 "잠자기"브라우저로 이벤트를 보낼 수 없으며, 그래도 백엔드 솔루션이어야하지만 프론트 엔드를 어떻게 업데이트하여 랩톱을 다시 깨울 때 로그 아웃 화면에 표시되도록해야합니까? 또는 컴퓨터?


7
세션 쿠킹 만료 날짜를 "현재 + 15 분"으로 설정하면됩니다. 마지막 화면이 계속 표시 될 수 있지만 쿠키가 만료 된 경우 해당 세션에서 작업 할 수 없습니다. "로그인 화면으로 부팅"-일정 시간 사용하지 않으면 컴퓨터를 자동으로 로그 아웃하는 OS 설정이 있습니다.
Lars Stegelitz

1
사이트가로드 될 때마다 세션 쿠키와 동일한 시간 초과로 Javascript 타이머를 초기화 할 수 있습니다 ... 타이머가 울리면 사용자는 오랫동안 비활성 상태입니다. 그런 다음 그를 로그 아웃 (AJAX 호출)하고 브라우저를 로그인 화면 또는 "죄송합니다. 비활성 상태로 인해 로그 아웃했습니다"화면으로 리디렉션합니다.)
Lars Stegelitz

1
좋아, 지금 대답을 추가하고있다.
Dato DT

1
이게 유용한가요?
Dato DT

1
@DatoDT 아니요, 하나는 laravel을 사용합니다. 2 개는 이미 시작 게시물에 표시된 laravel 소켓을 사용하고 있습니다. 나는 본질적으로 라 라벨 솔루션을 찾고 있습니다.
TheWebs

답변:


0

최신 정보

WebSocket 요청과 관련하여 Laravel WebSocket 을 사용한다고 가정합니다 pusher. Pusher.io 는 타임 아웃을 지원하지 않습니다. 이 지원 기사 "채널 푸셔 -js 클라이언트 라이브러리에 연결 타임 아웃 기능을 추가 할 계획입니까?"를 읽을 수 있습니다. . 출력 로그 이벤트를 볼 수 있도록 Laravel 디버그 모드 ( APP_DEBUG=true inside .env ) 를 활성화 laravel-websockets하고 터미널 ( php artisan websockets:serve) 에서 시작하면 테스트 할 수 있습니다 . 랩톱 덮개를 닫거나 컴퓨터를 최대 절전 모드 ( 절전 )로 설정하려고하면 이 이벤트와 관련된 메시지가 표시되지 않습니다. pusher프로토콜 로는 할 수 없습니다 . 이 존재 이벤트member_removed 탭을 닫거나 로그 아웃 할 때만 트리거됩니다. 물론 프레즌스 채널로 클라이언트 커스텀 이벤트를 트리거 할 수 있지만 클라이언트 측에 타이머를 설정해야 laravel-websockets하므로이 github 문제와 같은 서버 의 서비스 공급자를 만들어야 합니다. 웹 후크를 구현 하시겠습니까? " .

어떤 사람들은 다른 비슷한 질문을 제안했습니다.

...

  • 프런트 엔드에서 타이머를 실행하려면 ( 노트북 덮개를 닫으면 중지됩니다 )

이는 클라이언트 타이머가 최대 절전 모드에서 실행을 중단하므로 이전 위치에서 계속되기 때문입니다. 그러나 날짜 변수를 사용하여 시간을 절약하면 컴퓨터가 최대 절전 모드로 전환 될 때 해당 변수가 업데이트되지 않으므로 현재 시간과 비교할 때 날짜 변수확인하여 절전 모드에서 해제되는 시점을 알 수 있습니다 차이가 있으며 타이머 간격보다 큽니다.

클라이언트에서 시간 로직 구현

이 관련 Q / A에 대한 구현을 볼 수도 있습니다 . 어떤 데스크톱 브라우저에서 컴퓨터가 절전 모드에서 다시 시작되는지 감지 할 수 있습니까?

클라이언트에서 타이머를 설정하여 1 분마다 실행할 수 있습니다. 우리는 timer interval에 의존하지 않지만, 대신 마지막 타이머 이후의 시간 간격이 분 보다 큰 경우 해당 타이머는 외부 범위 날짜 변수를 검사합니다 15. 그렇다면 브라우저 / JS가 어떤 이유로 든 장치의 최대 절전 모드 ( 잠자기 )로 인해 실행이 중지 된 다음 사용자를 로그 아웃 경로로 리디렉션한다는 의미입니다.

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

이 간단한 예제를 확인할 수 있지만 여기 1에서 15초 로그 아웃 과 함께 두 번째 타이머를 사용 하십시오 . 많은 프로그램을 실행하는 경우 컴퓨터가 최대 절전 모드를 완료하고 실행을 중지하기 위해 메모리 상태를 저장하는 데 시간이 걸리므로 덮개를 닫은 상태에서 랩톱에서 테스트 한 다음 2 분에 15 초 후에 다시 여는 것이 가장 좋습니다.

웹 워커 예제

웹 워커 API 를 사용 하여 웹 워커를 훨씬 안전하게 설정할 수 있습니다.

페이지 JS 코드 :

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.js코드 :

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

여기서 동일한 15초 타이머 를 사용하여 웹 워커 예제를 확인할 수도 있습니다 .


이것은 15 초 후에 당신이 무엇을 찾고 있는지 확실하지 않습니다.
이슬람교 Elshobokshy

@IslamElshobokshy 당신이 맞아요, 캐치 주셔서 감사합니다. clientSession변수 를 업데이트하는 것을 잊었습니다 . 내 답변을 다시 확인할 수 있으며 웹 워커 예제도 추가했습니다.
Christos Lytras

여전히 작동하지 않는 샘플 예제를 업데이트하십시오. 첫 번째는 15 초 후에 무엇이든 로그 아웃합니다. 두 번째는 로그 아웃하지 않습니다.
이슬람교 Elshobokshy

@IslamElshobokshy 물론 업데이트했습니다. 문제가 발생하기 전에 예상대로 작동합니다. ?v=1끝 과 같은 매개 변수를 추가하지 않았거나 추가하지 않은 경우 페이지를 폐기하십시오 .
Christos Lytras

1
훌륭한 솔루션 + 3
AmerllicA

0

먼저, 은행 웹 사이트가 활동없이 15 분 후에 로그 아웃하는 이유를 확장 해 보겠습니다. 보안을위한 PCI 요구 사항입니다.

PCI-DSS 요구 사항 8.1.8 :

8.1.8 세션이 15 분 이상 유휴 상태 인 경우 사용자에게 다시 인증하여 터미널 또는 세션을 다시 활성화하도록 요청하십시오.

이것을 달성하기 위해 위해 솔루션은 실제로 생각보다 훨씬 원시적 입니다. 웹 소켓을 사용하거나 클라이언트 시스템 상태에 대해 아는 것도 필요하지 않습니다 (수면 또는 깨어남 또는 기타). 필요한 것은 해당 세션을 사용하는 현재 요청과 동일한 세션을 사용하는 마지막 요청 사이의 시간을 알고 15 분을 초과하지 않는 것입니다. 사용자 인 경우 다시 인증해야합니다. 그렇지 않은 경우 요청을 진행할 수 있습니다.

"세션 시간 초과"메시지

컴퓨터를 절전 모드로 전환하고 다시 깨울 때 세션 시간 초과 메시지가 어떻게 나타나는지 궁금 할 것입니다. 이 부분은 믿을 수 없을 정도로 간단합니다.

컴퓨터가 잠자기 상태가되면 브라우저는 실제로 모든 TCP / IP 연결을 끊고 자바 스크립트 엔진에서 이벤트 루프를 종료합니다. 따라서 타이머가 작동하지 않습니다. 그러나 브라우저가 다시 깨어날 때 페이지 자체를 포함하여 일부를 새로 고치려고 시도합니다. 따라서 페이지가 새로 고쳐지면 요청은 서버를 다시 호출하여 사용자를 다시 인증하도록 서버를 호출합니다.

그러나 이것은 일부 은행 웹 사이트가하는 자바 스크립트 메시지 모달 (당신이 말하는 경우)을 설명하지 않습니다. 또한 모든 시나리오에서 모든 브라우저가 페이지를 강제로 새로 고치는 것은 아닙니다. 따라서 다른 접근 방식을 취할 수 있습니다. 브라우저에 15 분 후에 시간 초과되는 타이머가있는 대신 단순히 페이지로드 시간을 자바 스크립트에 타임 스탬프로 저장하고 해당 타임 스탬프를 컴퓨터의 현재 타임 스탬프와 비교하는 1 초 간격 시간 초과를 가질 수 있습니다. 15 분 이상 떨어져 있으면 세션을 종료해야합니다.

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


};

컴퓨터가 절전 모드로 전환되고 타이머가 중지 되더라도 세션은 결국 서버 쪽에서 시간 초과되고 ( 자세한 내용은 아래 섹션 참조 ) 컴퓨터가 다시 깨어 나면 1 초 간격으로 타이머가 다시 시작되어 메시지 (컴퓨터가 절전 모드 일 때 시간이 초과 된 것처럼). 컴퓨터가 절전 모드로 전환 된 시간과 컴퓨터가 깨어 난 시간 사이의 시간 손실은 타임 스탬프가 메모리에 남아 있으므로 중요하지 않습니다. 클라이언트와 서버 간의 연결 끊기는 서버 측에서 세션을 올바르게 종료하기 위해이 정보를 전달할 필요가 없기 때문에 중요하지 않습니다. 서버는 클라이언트와의 통신없이 (즉 비동기 적으로 ) 자체 가비지 수집을 수행하고 세션을 종료 할 수 있습니다 .

믿거 나 말거나 은행은 고객 내부의 활동에 신경 쓰지 않습니다. 서버에 대한 요청 활동에만 관심이 있습니다. 따라서 사용자가 오랫동안 같은 페이지에있을 때 15 분 이상 세션을 활성 상태로 유지하는 방법에 대해 궁금한 경우 AJAX 요청을 백그라운드로 보내서 사용자에게 여전히 세션이 있는지 묻는 후 세션을 새로 고치십시오. 계속하고 싶다.

onload이전에 사용한 것과 동일한 이벤트 콜백 에서 수행 할 수 있습니다 .

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


};

서버 측에서 세션 종료 처리

서버 측에서 세션 종료를 처리하기 위해 몇 가지 접근 방식이 있습니다. 어떤 것을 사용 하느냐에 따라 다른 전술이 필요합니다. 하나는 PHP의 기본 세션 핸들러를 사용하고session.max_lifetime 15 분 후에 만료되도록 (이것은 세션 데이터를 서버 측에서 완전히 삭제하여 클라이언트 쿠키를 무효화합니다).

기본 세션 처리기 메커니즘을 사용하도록 설정하면 사용 된 처리기 (파일, memcached, redis, 사용자 정의 등)에 따라 문제가 발생할 수 있습니다.

파일 (기본 핸들러)을 사용하면 가비지 수집이 다음 두 가지 방법 중 하나로 발생합니다.

  • 대부분의 데비안 기반 시스템은 크론 작업을 통해 자체 GC를 수행합니다 (시나리오에 적합 함).
  • 다른 배포판은 PHP의 기본 GC 메커니즘이 그것을 처리하게합니다. 이는 각 수신 요청의 PHP에 대한 확률 적 결과를 기반으로 세션 파일의 파일 mtime을 확인하고 과거의 파일을 삭제합니다 session.max_lifetime. 이 접근 방식의 문제점은 트래픽이 적은 사이트 session.gc_probability에서 세션 파일을 정리하기 위해 GC를 호출하기 에 충분한 점수가 요청에 도달 할 때까지 ( 점수 에 따라) 세션이 오랫동안 서버에있을 수 있다는 것입니다 .

memcached 및 redis 기반 핸들러를 사용하면이 문제가 없습니다. 메모리를 자동으로 제거합니다. 세션은 수명이 지난 시간 동안 물리적 메모리에 계속 남아있을 수 있지만 데몬은 액세스 할 수 없습니다. 보안을 위해이 비트가 염려되면 세션을 암호화하거나 메모리 제거 GC 메커니즘이 더 엄격한 키 / 값 저장소를 찾을 수 있습니다.

커스텀 세션 핸들러를 사용하면 자신 만의 GC 메커니즘을 구축해야합니다. 이를 통해 세션의 최대 수명 간격을 전달 SessionHandlerInterface하는 gc방법을 구현 하고이 간격을 기준으로 세션의 수명이 지 났는지 확인하고 가비지 수집을 수행해야합니다.

또한 클라이언트 측의 비동기 AJAX 요청을 통해 세션 TTL을 확인하고 세션이 만료 된 경우 응답을 다시 보내는 별도의 엔드 포인트를 설정할 수 있습니다 (자바 스크립트가 사용자를 다시 인증하도록 함).


0

따라서 Idea는 setInterval 및 Sockets 뒤에 있으며 setInterval은 대부분의 브라우저에서 지원되며 자바 스크립트 WbsocketApi는 거의 모든 브라우저에서 지원됩니다.

간단한 개요 : setInterval ()-컴퓨터가 절전 / 일시 중지 / 최대 절전 모드 일 때이 함수의 동작은 다음과 같습니다.

다음 코드는 처음에 다음을 수행합니다 (동시에 가능하지만 연결을 수신하는 PHP server_socket을 시작합니다)

javascript websocket보다 api는 2 초마다 유닉스 타임 스탬프 밀리 초로 현재 타임 스탬프를 보냅니다 .1 초는 자신에게 달려 있습니다.

그 후 PHP 서버 소켓 이이 시간을 가져 와서 비교할 이전 시간과 같은 것이 있는지 확인합니다. 코드가 처음 인스턴스화 될 때 PHP에는 이전 시간과 같은 것이 없으므로 Javascript 웹 소켓에서 보낸 시간과 비교할 수 없습니다. 'prev_time'이라는 세션 에서이 시간을 절약하고 Javascript 소켓에서 다른 시간 데이터가 수신 될 때까지 기다리기 때문에 두 번째 사이클이 시작됩니다. 자바 스크립트 WebsocketApi에서 PHP 서버 소켓 새로운 시간 데이터가 새로 수신 된 시간 데이터와 비교하기 위해 이전 시간과 같은 것이 있는지 확인하면 PHP가 두 번째주기와 같이 'prev_time'이라는 세션이 존재하는지 확인합니다. 그것은 존재하고 가치를 잡고 다음을 수행합니다.$diff = $new_time - $prev_time, $ diff는 2 초 또는 2000 밀리 초입니다. setInterval주기는 2 초마다 발생하며 전송하는 시간 형식은 밀리 초입니다.

php보다 if($diff<3000)차이가 3000보다 작은 지 확인 하면 사용자가 활성 상태임을 알면 다시이 초를 조작 할 수 있습니다. 네트워크에서 가능한 지연 시간이 거의 불가능하기 때문에 3000을 선택하지만 항상주의해야합니다. PHP는 사용자가 활성화되어 있다고 판단하면 PHP $new_time는 새로 수신 된 값으로 'prev_time'세션을 재설정 하고 테스트 목적으로 자바 스크립트 소켓으로 메시지를 다시 보냅니다.

그러나 $diff3000 이상인 경우 무언가가 setInterval을 일시 중지하고 발생할 수있는 방법 만 있고 내가 말하는 것을 이미 알고 있다고 생각하므로 else( if($diff<3000)) 의 논리에서 특정 세션을 파괴하여 사용자를 로그 아웃 할 수 있습니다. 리디렉션하려면 텍스트를 javacript 소켓에 보내고 텍스트에 window.location = "/login"따라 실행할 로직을 만들 수 있습니다. 코드는 다음과 같습니다.

먼저 javascript를로드하는 것은 index.html 파일입니다.

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

그렇다면 그것은 실제로 아름답게 코딩되지는 않지만 자바 스크립트이지만 주석 읽기가 중요하다는 것을 알 수 있습니다.

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

이제 여기에 PHP 코드의 일부가 있습니다. 풀 코드가 있다고 걱정하지 마십시오. 그러나이 부분은 실제로 위에서 언급 한 작업이 다른 기능을 만날 것입니다. 그러나 Javascript 소켓을 디코딩하고 작업하기 때문에 실제 일입니다. 여기에 의견을 읽어보십시오.

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

?>

다음은 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;
}

참고 읽기 : $new_time변수는 $jsTime코드에 있습니다

php -f server_socket.php 다음 명령으로 php socket을 실행하여 파일을 복사하여 파일에 붙여 넣습니다. php -f server_socket.php localhost로 가서 콘솔이 열려 있는지 테스트합니다. (잠에서 hen을 때); 귀하의 executin은 사용자가 잠 들어있을 때가 아닌 잠 들어있을 때 발생합니다.이 순간 모든 것이 페이지 파일 (windows) 또는 swap (linux)에 캐시됩니다


php -f server_socket.php 다음 명령으로 php socket을 실행하여 파일을 복사하여 파일에 붙여 넣습니다. php -f server_socket.php localhost 로 가서 콘솔이 열려 있는지 테스트합니다. (잠에서 hen을 때); 귀하의 executin은 사용자가 잠 들어있을 때가 아니라 잠 들어있을 때 발생합니다. 그 순간 모든 것이 페이지 파일 (windows) 또는 swap (linux)에 캐시됩니다
Dato DT

0

은행 로그인 / 로그 아웃 시스템의 작동 방식에 대해 많은 논의를했습니다.

사례 -1 : 사용자가 활동중인 경우 무제한으로 사용자에게 웹 페이지 액세스

사용자가 로그인 할 때마다 백엔드에서 타이머를 시작하십시오 (원하는 시간 제한을 설정하십시오) .15 분이라고합시다. 이제 무슨 뜻입니까 ?? 이는 사용자가 웹 페이지에서 활동을 수행하지 않으면 로그 아웃한다는 의미입니다.

이제 전면에서 사용자 활동을 백엔드로 보낼 수 있습니다 (소켓 또는 롱 폴링을 사용하여 보낼 수 있음). 기본적으로 타이머를 재설정하고 사용자는 원하는 시간에 웹 페이지를 적극적으로 사용할 수 있습니다.

사용자가 PC를 절전 모드로 전환하면 타이머가 재설정되지 않으며 타이머가 종료되면 세션을 무효화 할 수 있습니다.

PC를 절전 모드로 전환하자마자 사용자 세션을 무효화하려면 세션 유효성 검사 시간 제한을 설정할 수 있습니다. 예를 들어 사용자가 로그인하면 10 초 동안 만 유효한 세션을 만들고 사용자 활동 요청을 받으면 타이머를 재설정하고 새 세션 키를 제공 할 수 있습니다.

이것이 도움이되기를 바랍니다. 궁금한 점이 있으면 알려주세요.


-1

기계가 잠자기 상태인지 감지하는 스크립트를 작성했습니다. 기계가 대기 모드에있을 때 모든 스크립트가 중지됩니다. 따라서 timeInterval 내에서 현재 시간을 추적하면 timeInterval이 현재 시간 빼기 (-)를 트리거 할 때마다 새 시간이 timeInterval에 충분히 가까워 야합니다. 따라서 타이머가 X 시간 동안 유휴 상태인지 확인하려면 시차가 X보다 큰지 확인할 수 있습니다.

예를 들어 컴퓨터가 15 초 이상 잠자기 상태인지 확인합니다. 컴퓨터를 잠자기 상태로두면 모든 프로세서를 생각하는 데 15 초가 더 걸립니다. (내 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

-1

Lambda Authorizers 및 Redis와 함께 AWS Cognito를 사용하여 똑같은 요구 사항을 구현 했으며이 단계에서 코드를 공유 할 수는 없지만이 구성 요소로 구현 된 방법을 모두 알려 줄 수 있으며 동일한 개념을 다른 구성 요소와 함께 사용할 수 있습니다 비 AWS 구성 요소.

먼저 비 활동 로그 아웃을 구현하면 누군가 컴퓨터를 끄는 것처럼 프런트 엔드 웹 사이트에서 로그 아웃하지 않는 것처럼 서버 쪽에서 로그 아웃해야합니다. 나는 ACTIVE사용자 개념을 사용했습니다. 사용자가 성공적으로 인증되면 Redis에서 TTL로 15 분의 TTL 키와 username값을 가진 항목을 저장합니다 ACTIVE(동일한 사용자에게 여러 세션을 동시에 허용하려면 username + sessionid 일 수 있음).

사용자가 ACTIVE유효한 토큰을 가지고 있을 때 사용자 지정 권한 부 여자 에서 보호 된 리소스에 대한 액세스 권한을 부여하고 가장 중요한 것은 username& 로 Redis에서 다른 작업을 수행하는 것 ACTIVE입니다.

사용자가 로그 아웃 할 때마다 ID 관리 솔루션 (Cognito)에서 로그 아웃하고로 표시합니다 INACTIVE. 사용자가 15 분 이내에 API에 도달하지 않으면 더 이상 항목을 입력 할 수 없습니다.ACTIVE 에 액세스 사용자 이름을 할 수 없으며 더 이상 API에 액세스 할 수 없으며 다시 로그인해야하므로 리디렉션됩니다.

이 접근 방식에는 고려해야 할 사항이 많이 있습니다. 한 가지 이유는 Authorizer가 종종 일정 시간 동안 결과를 캐시하는 것입니다. 예를 들어 결과를 5 분 동안 캐시하면 10 분 후에 사용자로 로그 오프 될 수 있습니다. ACTIVE항목을 새로 고치지 않는 권한 부 여기 대신 캐시에 도달 할 수 있습니다.

또한 특정 사용자의 ACTIVE가용성이 높고 장애 발생시 신속하게 복구 할 경우 저장하는 데 사용하는 모든 것을 확인하는 것이 중요합니다 .

이 방법으로 캐시 저장소를 사용하는 방법은 토큰 무효화가 OAuth2와 같은 상태 비 저장 권한 부여 프로토콜에 개선되는 방식과 유사합니다.

우리는 몇 달 동안이 접근법을 사용해 왔으며, 우리에게는 잘 작동하는 것 같습니다. 처리 해야하는 약간 성가신 요구 일 수 있습니다 .AWS 세계에서 사용할 준비가되어있을 것으로 예상했습니다 이것에 대한 상자 해결책의 그러나 아무 말도 없었다.


우리는 또한 펜 테스트를 견뎌냈습니다 (; 여기서 우리의 요구 사항은 처음부터 시작되었으며, 응용 프로그램은 금융 서비스 기반 제품이므로이를 요구 사항으로 구현해야했습니다)
Snickers3192
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.