Programing

유휴 사용자를 기반으로 Angularjs로 자동 로그 아웃

lottogame 2020. 10. 14. 07:17
반응형

유휴 사용자를 기반으로 Angularjs로 자동 로그 아웃


사용자가 비활성 상태인지 확인하고 angularjs를 사용하여 10 분 동안 비활성 상태가되면 자동으로 로그 아웃 할 수 있습니까?

jQuery를 사용하지 않으려 고했지만 angularjs에서이를 수행하는 방법에 대한 자습서 나 기사를 찾을 수 없습니다. 어떤 도움을 주시면 감사하겠습니다.


Ng-Idle이 상황에서 유용 할 수 있는 모듈을 작성했습니다 . 다음은 지침과 데모가 포함 된 페이지입니다.

기본적으로 사용자 활동 (클릭, 스크롤, 입력과 같은 이벤트)에 의해 중단 될 수있는 유휴 시간 동안 타이머를 시작하는 서비스가 있습니다. 서비스에서 메서드를 호출하여 시간 제한을 수동으로 중단 할 수도 있습니다. 시간 초과가 중단되지 않으면 사용자가 로그 아웃 될 것임을 경고 할 수있는 경고를 카운트 다운합니다. 경고 카운트 다운이 0에 도달 한 후에도 응답하지 않으면 애플리케이션이 응답 할 수있는 이벤트가 브로드 캐스팅됩니다. 귀하의 경우 세션을 종료하고 로그인 페이지로 리디렉션하라는 요청을 보낼 수 있습니다.

또한 일정 간격으로 일부 URL을 ping 할 수있는 연결 유지 서비스가 있습니다. 이것은 사용자가 활성 상태 인 동안 사용자의 세션을 유지하기 위해 앱에서 사용할 수 있습니다. 기본적으로 유휴 서비스는 연결 유지 서비스와 통합되어 유휴 상태가되면 핑을 일시 중단하고 돌아 오면 다시 시작합니다.

시작하는 데 필요한 모든 정보 위키의 자세한 내용과 함께 사이트 에 있습니다 . 그러나 다음은 시간 초과시 로그 아웃하는 방법을 보여주는 구성 스 니펫입니다.

angular.module('demo', ['ngIdle'])
// omitted for brevity
.config(function(IdleProvider, KeepaliveProvider) {
  IdleProvider.idle(10*60); // 10 minutes idle
  IdleProvider.timeout(30); // after 30 seconds idle, time the user out
  KeepaliveProvider.interval(5*60); // 5 minute keep-alive ping
})
.run(function($rootScope) {
    $rootScope.$on('IdleTimeout', function() {
        // end their session and redirect to login
    });
});

사용중인 데모 보기 angularjs및 브라우저 로그보기

<!DOCTYPE html>
<html ng-app="Application_TimeOut">
<head>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.20/angular.min.js"></script>
</head>

<body>
</body>

<script>

var app = angular.module('Application_TimeOut', []);
app.run(function($rootScope, $timeout, $document) {    
    console.log('starting run');

    // Timeout timer value
    var TimeOutTimerValue = 5000;

    // Start a timeout
    var TimeOut_Thread = $timeout(function(){ LogoutByTimer() } , TimeOutTimerValue);
    var bodyElement = angular.element($document);

    /// Keyboard Events
    bodyElement.bind('keydown', function (e) { TimeOut_Resetter(e) });  
    bodyElement.bind('keyup', function (e) { TimeOut_Resetter(e) });    

    /// Mouse Events    
    bodyElement.bind('click', function (e) { TimeOut_Resetter(e) });
    bodyElement.bind('mousemove', function (e) { TimeOut_Resetter(e) });    
    bodyElement.bind('DOMMouseScroll', function (e) { TimeOut_Resetter(e) });
    bodyElement.bind('mousewheel', function (e) { TimeOut_Resetter(e) });   
    bodyElement.bind('mousedown', function (e) { TimeOut_Resetter(e) });        

    /// Touch Events
    bodyElement.bind('touchstart', function (e) { TimeOut_Resetter(e) });       
    bodyElement.bind('touchmove', function (e) { TimeOut_Resetter(e) });        

    /// Common Events
    bodyElement.bind('scroll', function (e) { TimeOut_Resetter(e) });       
    bodyElement.bind('focus', function (e) { TimeOut_Resetter(e) });    

    function LogoutByTimer()
    {
        console.log('Logout');

        ///////////////////////////////////////////////////
        /// redirect to another page(eg. Login.html) here
        ///////////////////////////////////////////////////
    }

    function TimeOut_Resetter(e)
    {
        console.log('' + e);

        /// Stop the pending timeout
        $timeout.cancel(TimeOut_Thread);

        /// Reset the timeout
        TimeOut_Thread = $timeout(function(){ LogoutByTimer() } , TimeOutTimerValue);
    }

})
</script>

</html>

아래 코드는 순수한 자바 스크립트 버전입니다.

<html>
    <head>
        <script type="text/javascript">         
            function logout(){
                console.log('Logout');
            }

            function onInactive(millisecond, callback){
                var wait = setTimeout(callback, millisecond);               
                document.onmousemove = 
                document.mousedown = 
                document.mouseup = 
                document.onkeydown = 
                document.onkeyup = 
                document.focus = function(){
                    clearTimeout(wait);
                    wait = setTimeout(callback, millisecond);                       
                };
            }           
        </script>
    </head> 
    <body onload="onInactive(5000, logout);"></body>
</html>

최신 정보

@Tom 제안으로 솔루션을 업데이트했습니다.

<!DOCTYPE html>
<html ng-app="Application_TimeOut">
<head>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.20/angular.min.js"></script>
</head>

<body>
</body>

<script>
var app = angular.module('Application_TimeOut', []);
app.run(function($rootScope, $timeout, $document) {    
    console.log('starting run');

    // Timeout timer value
    var TimeOutTimerValue = 5000;

    // Start a timeout
    var TimeOut_Thread = $timeout(function(){ LogoutByTimer() } , TimeOutTimerValue);
    var bodyElement = angular.element($document);

    angular.forEach(['keydown', 'keyup', 'click', 'mousemove', 'DOMMouseScroll', 'mousewheel', 'mousedown', 'touchstart', 'touchmove', 'scroll', 'focus'], 
    function(EventName) {
         bodyElement.bind(EventName, function (e) { TimeOut_Resetter(e) });  
    });

    function LogoutByTimer(){
        console.log('Logout');
        ///////////////////////////////////////////////////
        /// redirect to another page(eg. Login.html) here
        ///////////////////////////////////////////////////
    }

    function TimeOut_Resetter(e){
        console.log(' ' + e);

        /// Stop the pending timeout
        $timeout.cancel(TimeOut_Thread);

        /// Reset the timeout
        TimeOut_Thread = $timeout(function(){ LogoutByTimer() } , TimeOutTimerValue);
    }

})
</script>
</html>

Plunker에서 업데이트 된 버전을 보려면 여기를 클릭하십시오.


이를 수행하는 다른 방법이 있어야하며 각 접근 방식은 특정 응용 프로그램에 다른 것보다 더 적합해야합니다. 대부분의 앱에서는 단순히 키 또는 마우스 이벤트를 처리하고 로그 아웃 타이머를 적절하게 활성화 / 비활성화 할 수 있습니다. 즉, 내 머리 위에 "멋진"AngularJS-y 솔루션이 다이제스트 루프를 모니터링하고 있는데, 마지막 [지정된 기간] 동안 아무 것도 트리거되지 않은 경우 로그 아웃됩니다. 이 같은.

app.run(function($rootScope) {
  var lastDigestRun = new Date();
  $rootScope.$watch(function detectIdle() {
    var now = new Date();
    if (now - lastDigestRun > 10*60*60) {
       // logout here, like delete cookie, navigate to login ...
    }
    lastDigestRun = now;
  });
});

Boo의 접근 방식을 사용했지만 사용자가 다른 다이제스트가 실행 된 후에 만 ​​시작되었다는 사실이 마음에 들지 않습니다. 즉, 사용자가 페이지 내에서 작업을 시도한 다음 즉시 시작될 때까지 로그인 상태를 유지한다는 의미입니다.

마지막 작업 시간이 30 분 이상 지난 경우 매 분마다 확인하는 간격을 사용하여 강제로 로그 오프하려고합니다. $ routeChangeStart에 연결했지만 Boo의 예에서와 같이 $ rootScope. $ watch에 연결할 수도 있습니다.

app.run(function($rootScope, $location, $interval) {

    var lastDigestRun = Date.now();
    var idleCheck = $interval(function() {
        var now = Date.now();            
        if (now - lastDigestRun > 30*60*1000) {
           // logout
        }
    }, 60*1000);

    $rootScope.$on('$routeChangeStart', function(evt) {
        lastDigestRun = Date.now();  
    });
});

angular-activity-monitor여러 공급자를 주입하는 것보다 더 간단한 방법으로 사용할 수도 있으며 , 다이제스트 루프를 수동으로 트리거하는 것을 방지하기 위해 setInterval()(vs. angular 's $interval)를 사용 합니다 (이는 의도하지 않게 항목을 유지하는 것을 방지하는 데 중요합니다).

궁극적으로 사용자가 비활성 상태이거나 가까워지는시기를 결정하는 몇 가지 이벤트 만 구독하면됩니다. 따라서 10 분 동안 활동이없는 사용자를 로그 아웃하려면 다음 스 니펫을 사용할 수 있습니다.

angular.module('myModule', ['ActivityMonitor']);

MyController.$inject = ['ActivityMonitor'];
function MyController(ActivityMonitor) {
  // how long (in seconds) until user is considered inactive
  ActivityMonitor.options.inactive = 600;

  ActivityMonitor.on('inactive', function() {
    // user is considered inactive, logout etc.
  });

  ActivityMonitor.on('keepAlive', function() {
    // items to keep alive in the background while user is active
  });

  ActivityMonitor.on('warning', function() {
    // alert user when they're nearing inactivity
  });
}

나는 Buu의 접근 방식을 시도했지만 $ interval 및 $ timeout 함수 실행을 포함하여 다이 제스터를 실행하도록 트리거하는 수많은 이벤트로 인해 제대로 얻을 수 없었습니다. 이렇게하면 사용자 입력에 관계없이 응용 프로그램이 유휴 상태가되지 않는 상태가됩니다.

실제로 사용자 유휴 시간을 추적해야하는 경우 좋은 각도 접근 방식이 있는지 확실하지 않습니다. https://github.com/witoldsz/angular-http-auth 여기에 Witoldz가 더 나은 접근 방식을 제시한다고 제안합니다 . 이 접근 방식은 자격 증명이 필요한 작업을 수행 할 때 사용자에게 재 인증하라는 메시지를 표시합니다. 사용자가 인증되면 이전에 실패한 요청이 다시 처리되고 아무 일도 일어나지 않은 것처럼 응용 프로그램이 계속됩니다.

이는 사용자의 인증이 만료 되더라도 여전히 애플리케이션 상태를 유지하고 작업을 잃지 않을 수 있기 때문에 사용자가 활성 상태 인 동안 사용자의 세션이 만료 될 수 있다는 우려를 처리합니다.

클라이언트에 일종의 세션 (쿠키, 토큰 등)이있는 경우 해당 세션도 볼 수 있으며 만료되면 로그 아웃 프로세스를 트리거 할 수 있습니다.

app.run(['$interval', function($interval) {
  $interval(function() {
    if (/* session still exists */) {
    } else {
      // log out of client
    }
  }, 1000);
}]);

업데이트 : 여기에 우려를 보여주는 플렁크가 있습니다. http://plnkr.co/edit/ELotD8W8VAeQfbYFin1W . 이것이 증명하는 것은 다이 제스터 실행 시간이 간격이 틱할 때만 업데이트된다는 것입니다. 간격이 최대 개수에 도달하면 소화기가 더 이상 실행되지 않습니다.


ng-Idle은 갈 길처럼 보이지만 Brian F의 수정 사항을 파악할 수 없었고 수면 세션에도 시간 초과를 원했고 매우 간단한 사용 사례를 염두에 두었습니다. 나는 그것을 아래 코드로 줄였습니다. 이벤트를 연결하여 시간 초과 플래그를 재설정합니다 ($ rootScope에 느리게 배치됨). 사용자가 돌아올 때 (그리고 이벤트를 트리거 할 때) 타임 아웃이 발생했음을 감지하지만 그 정도면 충분합니다. angular의 $ location을 여기서 작업 할 수는 없지만 document.location.href를 사용하면 작업이 완료됩니다.

.config가 실행 된 후 내 app.js에 이것을 붙였습니다.

app.run(function($rootScope,$document) 
{
  var d = new Date();
  var n = d.getTime();  //n in ms

    $rootScope.idleEndTime = n+(20*60*1000); //set end time to 20 min from now
    $document.find('body').on('mousemove keydown DOMMouseScroll mousewheel mousedown touchstart', checkAndResetIdle); //monitor events

    function checkAndResetIdle() //user did something
    {
      var d = new Date();
      var n = d.getTime();  //n in ms

        if (n>$rootScope.idleEndTime)
        {
            $document.find('body').off('mousemove keydown DOMMouseScroll mousewheel mousedown touchstart'); //un-monitor events

            //$location.search('IntendedURL',$location.absUrl()).path('/login'); //terminate by sending to login page
            document.location.href = 'https://whatever.com/myapp/#/login';
            alert('Session ended due to inactivity');
        }
        else
        {
            $rootScope.idleEndTime = n+(20*60*1000); //reset end time
        }
    }
});

Buu의 다이제스트 사이클 시계는 천재라고 생각합니다. 공유해 주셔서 감사합니다. 다른 사람들이 언급했듯이 $ interval도 다이제스트주기를 실행합니다. 자동 로그 아웃을 위해 다이제스트 루프를 일으키지 않는 setInterval을 사용할 수 있습니다.

app.run(function($rootScope) {
    var lastDigestRun = new Date();
    setInterval(function () {
        var now = Date.now();
        if (now - lastDigestRun > 10 * 60 * 1000) {
          //logout
        }
    }, 60 * 1000);

    $rootScope.$watch(function() {
        lastDigestRun = new Date();
    });
});

나는 이것을 위해 ng-idle을 사용하고 약간의 로그 아웃과 토큰 null 코드를 추가했으며 정상적으로 작동합니다. 이것을 시도해 볼 수 있습니다. 멋진 모듈을 만들어 주신 @HackedByChinese에게 감사드립니다.

에서 IDLETIMEOUT 난 그냥 내 세션 데이터 및 토큰을 삭제했다.

내 코드는 다음과 같습니다.

$scope.$on('IdleTimeout', function () {
        closeModals();
        delete $window.sessionStorage.token;
        $state.go("login");
        $scope.timedout = $uibModal.open({
            templateUrl: 'timedout-dialog.html',
            windowClass: 'modal-danger'
        });
    });

더 큰 프로젝트에서 이것을 사용하는 사람에 대한 답변을 확장하고 싶습니다. 실수로 여러 이벤트 핸들러를 연결할 수 있으며 프로그램이 이상하게 작동합니다.

그 제거하기 위하여는, 나는 당신이 부를 것이다있는 공장에 의해 노출 싱글 기능을 사용 inactivityTimeoutFactory.switchTimeoutOn()하고 inactivityTimeoutFactory.switchTimeoutOff()당신의 각 응용 프로그램에서 각각 활성화에 의한 활동 기능에 로그 아웃을 비활성화합니다.

이렇게하면 시간 제한 프로 시저를 활성화하려고 시도하는 횟수에 관계없이 이벤트 처리기의 단일 인스턴스 만 실행하도록하여 사용자가 다른 경로에서 로그인 할 수있는 애플리케이션에서 더 쉽게 사용할 수 있습니다.

내 코드는 다음과 같습니다.

'use strict';

angular.module('YOURMODULENAME')
  .factory('inactivityTimeoutFactory', inactivityTimeoutFactory);

inactivityTimeoutFactory.$inject = ['$document', '$timeout', '$state'];

function inactivityTimeoutFactory($document, $timeout, $state)  {
  function InactivityTimeout () {
    // singleton
    if (InactivityTimeout.prototype._singletonInstance) {
      return InactivityTimeout.prototype._singletonInstance;
    }
    InactivityTimeout.prototype._singletonInstance = this;

    // Timeout timer value
    const timeToLogoutMs = 15*1000*60; //15 minutes
    const timeToWarnMs = 13*1000*60; //13 minutes

    // variables
    let warningTimer;
    let timeoutTimer;
    let isRunning;

    function switchOn () {
      if (!isRunning) {
        switchEventHandlers("on");
        startTimeout();
        isRunning = true;
      }
    }

    function switchOff()  {
      switchEventHandlers("off");
      cancelTimersAndCloseMessages();
      isRunning = false;
    }

    function resetTimeout() {
      cancelTimersAndCloseMessages();
      // reset timeout threads
      startTimeout();
    }

    function cancelTimersAndCloseMessages () {
      // stop any pending timeout
      $timeout.cancel(timeoutTimer);
      $timeout.cancel(warningTimer);
      // remember to close any messages
    }

    function startTimeout () {
      warningTimer = $timeout(processWarning, timeToWarnMs);
      timeoutTimer = $timeout(processLogout, timeToLogoutMs);
    }

    function processWarning() {
      // show warning using popup modules, toasters etc...
    }

    function processLogout() {
      // go to logout page. The state might differ from project to project
      $state.go('authentication.logout');
    }

    function switchEventHandlers(toNewStatus) {
      const body = angular.element($document);
      const trackedEventsList = [
        'keydown',
        'keyup',
        'click',
        'mousemove',
        'DOMMouseScroll',
        'mousewheel',
        'mousedown',
        'touchstart',
        'touchmove',
        'scroll',
        'focus'
      ];

      trackedEventsList.forEach((eventName) => {
        if (toNewStatus === 'off') {
          body.off(eventName, resetTimeout);
        } else if (toNewStatus === 'on') {
          body.on(eventName, resetTimeout);
        }
      });
    }

    // expose switch methods
    this.switchOff = switchOff;
    this.switchOn = switchOn;
  }

  return {
    switchTimeoutOn () {
      (new InactivityTimeout()).switchOn();
    },
    switchTimeoutOff () {
      (new InactivityTimeout()).switchOff();
    }
  };

}

참고 URL : https://stackoverflow.com/questions/19168330/auto-logout-with-angularjs-based-on-idle-user

반응형