[Angular] 閒置登出作法
app.componemt.ts
偵測事件
// 如自動登出功能有bug 則停用以下--------
@HostListener('window:keyup', [])
@HostListener('window:click', [])
@HostListener('window:wheel', [])
@HostListener('window:mousemove', [])
resetTimer() {
this.authService.notifyUserAction();
}
authService
export class AuthService {
isLoggedIn = false;
// ! 閒置登出時間請更改這參數的數字
endtimeSet = 30;
// 這邊讓單位變成分鐘秒
endTime = this.endtimeSet * 60;
// store the URL so we can redirect after logging in
redirectUrl: string;
constructor(private router: Router) {}
// 偵測動作後重置閒置登出時間功能
userActionOccuredSubject: Subject<void> = new Subject();
get userActionOccured(): Observable<void> {
return this.userActionOccuredSubject.asObservable();
}
// 偵測動作後重置閒置登出時間功能
notifyUserAction() {
this.userActionOccuredSubject.next();
this.setTime();
}
login(): Observable<boolean> {
return of(true).pipe(
delay(1000),
tap(val => (this.isLoggedIn = true)),
);
}
logout(): void {
this.isLoggedIn = false;
console.log('登出');
this.router.navigate(['login']);
}
// 把時間寫進去localStorage
setTime() {
localStorage.setItem(
'expiredDate',
addMinutes(new Date(), 1, this.endTime).getTime().toString(),
);
}
}
function addMinutes(date, minutes, endTime) {
return new Date(date.getTime() + minutes * 1000 * endTime);
}
在要實作偵測閒置登出的html
<app-inactivity-timer></app-inactivity-timer>
inactivity timer 元件
export class InactivityTimerComponent implements OnInit {
notify$ = new Subject();
constructor(
private authService: AuthService,
private zone: NgZone,
public dialog: MatDialog,
) {
this.authService.setTime();
this.zone.runOutsideAngular(() => {
this.timeCountDown();
});
}
ngOnInit() {
this.notify$.subscribe(() => {
const idleLogoutRef = this.dialog.open(AlertDialogComponent, {
width: '',
disableClose: true,
data: {
fieldTypeName: 'inActiveLogoutAlert',
alertTitle: '提醒',
alertContent: '您好,您已閒置30分鐘,並將於15秒後登出。',
},
});
// 如果超過時間沒回應就登出
idleLogoutRef.afterOpened().subscribe(_ => {
setTimeout(() => {
this.dialog.closeAll();
// idleLogoutRef.close();
this.authService.logout();
}, 15000);
});
// 根據使用者選擇繼續編輯還是登出
idleLogoutRef.afterClosed().subscribe(result => {
if (result === 'keep') {
this.authService.setTime();
this.timeCountDown();
} else if (result === 'logout') {
this.authService.logout();
}
});
});
}
ngOnDestroy() {
this.notify$.next();
this.notify$.complete();
}
timeCountDown() {
const i = setInterval(() => {
const expiredDate = +localStorage.getItem('expiredDate');
// console.log(Math.floor(new Date().getTime() - expiredDate) / 1000);
if (new Date().getTime() - expiredDate > 0) {
this.zone.run(() => {
this.notify$.next();
});
clearInterval(i);
}
}, 1000);
}
}
alertDialog 提醒視窗
<!-- 閒置登出提醒 -->
<div class="" *ngIf="data.fieldTypeName === 'inActiveLogoutAlert'">
<div class="" fxLayout="row" fxLayoutAlign="center center" fxLayoutGap="16px">
<mat-icon color="warn"> warning</mat-icon>
<h3>
{{ data.alertTitle }}
</h3>
</div>
<mat-dialog-content
><b>{{ data.alertContent }}</b></mat-dialog-content
>
<div mat-dialog-actions fxLayoutAlign="center center">
<button mat-flat-button color="accent" (click)="onIdleSelect('logout')">
登出
</button>
<button mat-flat-button color="accent" (click)="onIdleSelect('keep')">
返回繼續
</button>
</div>
</div>
-----------------------------------------------
但是這做法會導致build時出現錯誤
ERROR in (1,1): Directive AppComponent, Expected 0 arguments, but got 1.
(1,1): Directive AppComponent, Expected 0 arguments, but got 1.
(1,1): Directive AppComponent, Expected 0 arguments, but got 1.
(1,1): Directive AppComponent, Expected 0 arguments, but got 1.
所以要用這個做法解決
------------------------------------------
AngularJS 解法
留言
張貼留言