ユーザーがしばらくアイドル状態の場合、ユーザーをログアウトする必要があるという要件があります。ng-idle 0.3.2 を使用しています。
ブラウザで複数のタブ/ウィンドウが開いていると問題が発生します。タブで作業していて、アクティブでないタブがログアウトされているのに、作業中のアクティブなタブがアクティブであるため、まだログインしている場合。
別の同様のタブで作業しているときに、非アクティブなタブからログアウトできないようにするにはどうすればよいですか?
localStorage を使用して、アプリを実行している任意のタブで最後に確認されたアクティビティ イベントのタイムスタンプを保存します。実行中のアプリのすべてのインスタンスで、数秒ごとにその値をポーリングします。更新されている場合は、ng-idle タイマーをリセットして、早すぎるログアウト (または $idleTimeout イベントがブロードキャストされたときに発生するように設定したアクション) を回避します。
上記の動作を具現化するディレクティブを作成します。
.directive('idle', function($idle, $timeout, $interval){
return {
restrict: 'A',
link: function(scope, elem, attrs) {
var timeout;
var timestamp = localStorage.lastEventTime;
// Watch for the events set in ng-idle's options
// If any of them fire (considering 500ms debounce), update localStorage.lastEventTime with a current timestamp
elem.on($idle._options().events, function(){
if (timeout) { $timeout.cancel(timeout); }
timeout = $timeout(function(){
localStorage.setItem('lastEventTime', new Date().getTime());
}, 500);
});
// Every 5s, poll localStorage.lastEventTime to see if its value is greater than the timestamp set for the last known event
// If it is, reset the ng-idle timer and update the last known event timestamp to the value found in localStorage
$interval(function() {
if (localStorage.lastEventTime > timestamp) {
$idle.watch();
timestamp = localStorage.lastEventTime;
}
}, 5000);
}
}
})
ディレクティブ属性を body タグに追加して、ページ内のすべてのマウスおよびキーボード イベントが確実に検出されるようにします。
<body ng-app="myApp" idle>
この Plunk を開いて複数のタブで実行し、それぞれにコンソールを追加します。本文のコンテンツの上にマウス カーソルを移動し、両方のコンソールに記録されたイベントを確認します。
私はまだ ngIdle を使用していませんが、通常、これらの状況ではサーバーと通信する必要があります。つまり、$keepalive イベントで、サーバーにリクエストを送信して、セッションの最後のアクティビティ時間を保存します。$idleWarn で、サーバーにリクエストを送信して最新のアクティビティ タイム スタンプを取得します。ユーザーが他のタブでアクティブな場合は、最近のタイムスタンプを取得するため、タイムアウト プロセスを停止してキープアライブを送信できます。