사용자가 비활성 상태인지 확인하고 angularjs를 사용하여 10 분 동안 비활성 상태가되면 자동으로 로그 아웃 할 수 있습니까?
jQuery를 사용하지 않으려 고했지만 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
});
});
Idle.watch()
에 .run()
함수 IdleTimeout
내가 그랬어 때까지 이벤트가 전혀 발사되지 않았다. 나는 Idle.watch()
당신의 github 데모 에서 호출을 보았 으므로 그것이 내가 얻은 곳입니다.
사용중인 데모 보기 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>
bodyElement.on(...)
하고 내부에서 LogoutByTimer
실행 해야합니다bodyElement.off(...)
이를 수행하는 방법은 여러 가지가 있어야하며 각 접근 방식은 특정 애플리케이션에 더 잘 맞아야합니다. 대부분의 앱에서는 단순히 키 또는 마우스 이벤트를 처리하고 로그 아웃 타이머를 적절하게 활성화 / 비활성화 할 수 있습니다. 즉, 내 머리 위에 "멋진"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();
});
});
$rootScope.$watch
에 전환을 요구,이 경우 setInterval
이후, $interval
A는 각 함수 호출에 소화 트리거 효과적으로를 재설정 lastDigestRun
.
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();
}
};
}