为 Ionic/Angular 实现 Session Timeout 服务,每次新的用户交互都会重置 Timer

Posted

技术标签:

【中文标题】为 Ionic/Angular 实现 Session Timeout 服务,每次新的用户交互都会重置 Timer【英文标题】:Implementing Session Timeout service for Ionic/Angular, with Timer Reset with each new user interaction 【发布时间】:2018-01-30 15:31:03 【问题描述】:

我正在尝试调整我为会话超时创建的一些代码。 每当用户与该功能交互时,我想重置计时器以再次开始倒计时。我很难弄清楚如何将类似的代码注入到这个example

C# 代码 - 我正在尝试集成:


var update = new Subject<bool>();
var res =
    update
        .Select(x => Observable.Interval(TimeSpan.FromSeconds(10.0)))
        .Switch();
res
    .Subscribe(_ => Console.WriteLine("Status sent."));
update.OnNext(true);

res
    .Subscribe(_ =>
    
        update.OnNext(true);
        Console.WriteLine("Status sent.");
    );

据我所知,Typescript RxJS 相当于 RxJS 库的 C# 风格,我的变量名映射是:

C#/example Typescript/mineupdate resetManager.Select .map(来自here-(见标签标题)).OnNext .next.Interval .timer

我在想我可以插入一个 do 并链接 resetManager - 但由于一个是布尔值而另一个是 AuthState 我似乎遇到了困难。

我想知道 RxJS 大师是否可以提供建议。干杯。


import  Injectable            from '@angular/core';
import  Observable            from 'rxjs/Observable';
import  BehaviorSubject       from 'rxjs/BehaviorSubject';
import                               'rxjs/add/operator/map';
import                               'rxjs/add/operator/filter';
import                               'rxjs/add/Observable/timer';
import                               'rxjs/add/operator/do';
import                               'rxjs/add/operator/switch';
@Injectable()
export class AuthService 
  private authState:    AuthState;
  private authManager:  BehaviorSubject<AuthState>;
  public  authChange$:  Observable<AuthState>;
  private resetManager: Subject<boolean>;
  constructor() 
    this.authManager = new BehaviorSubject(AuthState.LOGGED_OUT);
    this.authChange$ = this.authManager.asObservable();
    this.authChange$
      .filter((authState:AuthState) => authState === AuthState.LOGGED_IN)
      .map(   (authState:AuthState) => Observable.timer(SESSION_TIMEOUT))
      .do(    () => 
        console.log('Logged In. Session Timout counting down from now'))
      .switch()
      .subscribe( () => console.log('Timer ended: Logging out')
                         this.logout();
                        );
  

  login() 
    this.setAuthState(AuthState.LOGGED_IN);
  
  logout() 
    this.setAuthState(AuthState.LOGGED_OUT);
  

  resetSessionTimer() 
    this.resetManager.next(true);
   

  emitAuthState():void 
    this.authManager.next(this.authState);
  

  private setAuthState(newAuthState:AuthState):void 
    console.log('AuthService: setAuthState: ', 
        AuthState[newAuthState.toString()]);
    if (newAuthState != this.authState) 
      this.authState = newAuthState;
      this.emitAuthState();
    
  

export enum AuthState 
  LOGGED_IN,
  LOGGED_OUT


const SESSION_TIMEOUT = 5000;

【问题讨论】:

【参考方案1】:

我终于想出了如何做到这一点......

import  Events                from 'ionic-angular';
import  Observable            from 'rxjs/Observable';
import  Subscription          from 'rxjs/Subscription';
import                               'rxjs/add/observable/interval';
import                               'rxjs/add/operator/mapTo';
import                               'rxjs/add/observable/defer';
import                               'rxjs/add/observable/of';
import                               'rxjs/add/operator/merge';
import                               'rxjs/add/operator/scan';
import                               'rxjs/add/operator/filter';
import                               'rxjs/add/operator/switchMap';
import  BehaviorSubject       from 'rxjs/BehaviorSubject';

export  enum AuthState 
  LOGGED_IN,
  LOGGED_OUT


const SESSION_TIMEOUT = 10; // seconds

export class AuthService 
  private timer:         number;
  private tick$:         Observable<number>;
  private countDown$:    Observable<number>;
  private subscriptions:Subscription[];

  constructor(
    private events:Events
  ) 
    this.tick$ =Observable.interval(1000).mapTo(-1);
    this.countDown$ = Observable
      .defer(() => Observable.of(this.timer))
      .merge(this.tick$)
      .scan((acc,curr) => acc + curr)
    this.events.subscribe(RESET_COUNTDOWN, (action:string) => 
      this.resetSessionTimer(action);
    );
  

  beginCountDown() 
    let sub:Subscription;
    while (this.subscriptions.length > 0) 
      sub = this.subscriptions.pop();
      sub.unsubscribe();
    ;
    this.timer = SESSION_TIMEOUT;
    sub = this.countDown$
      .filter(timer => timer >= 0)
      .subscribe(timer => 
        this.timer = timer;
         if (this.timer === 1) 
           this.logout();
         
         console.log(this.timer);
        );
    this.subscriptions.push(sub);
  

  resetSessionTimer(action:string) 
    console.log('AuthService: resetSessionTimer(): ' + action);
    this.beginCountDown();
   

  emitAuthState():void 
    this.authManager.next(this.authState);
  

  private setAuthState(newAuthState:AuthState):void 
    if (newAuthState != this.authState) 
      this.authState = newAuthState;
      this.emitAuthState();
    
  
  login(
   clickStream$: BehaviorSubject<any>
  ) 

     this.response$ = clickStream$.switchMap(click =>  
                      return this.webServiceUtil.testLogin();
                                                      
                                            );
     this.response$.subscribe((response:Response) => 
          this.setAuthState(AuthState.LOGGED_IN);
      ,
     (err:any)          => 
         this.setAuthState(AuthState.LOGGED_OUT);  
     )
  

  logout() 
      if (this.authState === AuthState.LOGGED_IN) 
         this.setAuthState(AuthState.LOGGED_OUT);
      
  

RESET_COUNTDOWN 事件可能会在页面更改或执行 HTTP 请求时触发。这将迫使倒计时重新开始,而只有一个订阅,因此会跟踪一系列订阅。您会在重置时立即取消。

【讨论】:

以上是关于为 Ionic/Angular 实现 Session Timeout 服务,每次新的用户交互都会重置 Timer的主要内容,如果未能解决你的问题,请参考以下文章

Cordova笔记三:ionic+angular+cordova技术栈

如何将 Ionic3 angular4 混合应用程序构建为 ios .ipa 文件?

Ionic & Angular - iOS 上的 Ion 日期时间设计

在 ionic 4 + Angular 中将日期转换为 DD/MM/YYYY

如何在 javascript (ionic | Angular | NodeJS | MongoDB) 中将包含对象的数组展平和减少为逗号分隔的字符串

如何在 Ionic/Angular 中添加 OAuth facebook 登录?