【问题标题】:Automatic logout in Angular 2 after few minutes几分钟后在Angular 2中自动注销
【发布时间】:2018-02-05 07:17:42
【问题描述】:

我想实现一个功能(在 Angular2 中),即登录后,如果用户保持浏览器空闲 30 分钟,他应该在 30 分钟后回来时注销。这只能由前端完成。

我正在使用 Angular 2.4 版的 Angular CLI

如何在我的 Angular2 应用程序中实现此功能?

【问题讨论】:

标签: angular angular2-template angular2-services angular2-directives


【解决方案1】:
import { Injectable } from "@angular/core";
import { Router } from '@angular/router'
const MINUTES_UNITL_AUTO_LOGOUT = 60 // in mins
const CHECK_INTERVAL = 15000 // in ms
const STORE_KEY =  'lastAction';
@Injectable()
export class AutoLogoutService {
 public getLastAction() {
    return parseInt(localStorage.getItem(STORE_KEY));
  }
 public setLastAction(lastAction: number) {
    localStorage.setItem(STORE_KEY, lastAction.toString());
  }

  constructor(private router: Router) {
    this.check();
    this.initListener();
    this.initInterval();
    localStorage.setItem(STORE_KEY,Date.now().toString());
  }

  initListener() {
    document.body.addEventListener('click', () => this.reset());
    document.body.addEventListener('mouseover',()=> this.reset());
    document.body.addEventListener('mouseout',() => this.reset());
    document.body.addEventListener('keydown',() => this.reset());
    document.body.addEventListener('keyup',() => this.reset());
    document.body.addEventListener('keypress',() => this.reset());
  }

  reset() {
    this.setLastAction(Date.now());
  }

  initInterval() {
    setInterval(() => {
      this.check();
    }, CHECK_INTERVAL);
  }

  check() {
    const now = Date.now();
    const timeleft = this.getLastAction() + MINUTES_UNITL_AUTO_LOGOUT * 60 * 1000;
    const diff = timeleft - now;
    const isTimeout = diff < 0;

    if (isTimeout)  {
      localStorage.clear();
      this.router.navigate(['./login']);
    }
  }
}

【讨论】:

  • 我认为代码很有用,谢谢。我只是在其中添加了一些东西。我明确地调用了 init 例程,因为我发现它们没有在合适的时间在构造函数中被调用。 (不太清楚为什么)。我还调用了一个“destroy”方法,它也删除了事件侦听器。最后在检查方法中,我还检查他们当前是否已登录。否则我发现我被从我的应用程序的用户不需要登录的区域转发到登录页面。
  • 很高兴它可以提供帮助。您可以根据您的要求进行更改。有几种方法可以做到。检查也可以在初始化之后进行。
  • 你能告诉我,如何实现和使用它吗?我应该将它添加到 module.ts 的哪个位置,网页如何对其做出反应并自动注销?我必须以某种方式在每个控制器中添加它还是可以全局执行此操作?谢谢
  • 因为它是一个服务,所以在你的父模块中提供它,比如 app-module。因此,它将在您的整个项目中可用。您必须在要启动自动注销功能的任何页面上更新 localstorage 值。就我而言,它是在登录页面之后。
  • 这似乎很有用.....但是你能告诉我应该从哪里调用这个服务,从 app.component 的 ngoninit(),还是从其他地方?
【解决方案2】:

我需要做类似的事情并创建了这个:https://github.com/harunurhan/idlejs

它不是专门针对 Angular 的,但它是用typescript 编写的,所以你可以得到官方的打字。

它简单且可配置,没有任何依赖关系。一些例子:

import { Idle } from 'idlejs/dist';

// with predefined events on `document`
const idle = new Idle()
  .whenNotInteractive()
  .within(60)
  .do(() => console.log('IDLE'))
  .start();

您还可以使用自定义事件目标和事件:

const idle = new Idle()
  .whenNot([{
    events: ['click', 'hover'],
    target: buttonEl,
  },
  {
    events: ['click', 'input'],
    target: inputEl,
  },
  ])
  .within(10)
  .do(() => called = true)
  .start();

【讨论】:

  • 我希望你还在维护你的仓库??
  • 我是..它似乎不活跃,因为它只是为我工作而没有任何问题,我不需要额外的功能...如果您有功能请求或发现错误,请随意创建一个问题:)
【解决方案3】:

基本上,您需要做的是设置一个标志以防任何客户端活动,然后在 30 分钟后您必须检查该标志。如果未设置标志,则表示用户未处于活动状态,因此您可以执行logout() 操作。

这里有一些你可能会觉得有用的代码示例(使用ngrx)。

export class ClientActiveService {
  constructor(
    private store: Store<fromRoot.State>,
  ) { }

  run() {
    window.onload = () => { this.setActive(); };
    window.onmousemove = () => { this.setActive(); };
    window.onmousedown = () => { this.setActive(); }; 
    window.onclick = () => { this.setActive(); };
    window.onscroll = () => { this.setActive(); }; 
    window.onkeypress = () => { this.setActive(); };
  }

  setActive() {
     this.store.select(fromRoot.getClientActive)
     .take(1)
     .subscribe((active) => {
        if (!active) {
          this.store.dispatch(new layout.ClientActiveAction());
        }
      });
  }
}

ClientActiveService 是一个服务,如果客户端处于活动状态,它只会发出一个动作。在app.component.ts 之类的某个地方,您必须注入该服务并调用this.clientActiveService.run();

然后,您必须在代码中的某个位置设置一个 30 分钟的计时器,您可以在其中订阅 ClientInactiveAction 操作

    setInterval(() => {
      this.store.select(fromRoot.getClientActive)
      .take(1)
      .subscribe((active) => {
        if (!active) {
          this.auth.logout();
        }
      });
    }, 30 * 60 * 1000);

如果你不使用ngrx,你可以设置一个variable/flag 来代替 ClientActiveService 服务。然后在setTimeout() 中检查 该变量并执行您的logout() 操作

否则你可能想使用ng2-idle 库。在这种情况下,Angular 2 - Logout using ng2-idle 可能会有所帮助。

【讨论】:

  • 我正在创建 ClientActiveService,但它在此类的构造函数中显示错误:'cannot find nameSpace fromRoot'
  • @ErVipinSharma 如果您不使用ngrx,只需取出private store: Store&lt;fromRoot.State&gt; 和属于它的所有相关代码
  • import * as fromRoot from '@ngrx/store'; 不接缝是正确的。您应该从reducers 导入类似import * as fromRoot from '../reducers'; 的内容,只需输入正确的路径即可。
  • 您正在应用程序中定义自己的减速器,请查看ngrx 指南gist.github.com/btroncone/a6e4347326749f938510github.com/ngrx/platform/tree/master/example-app 以获取更多详细信息
  • window onclick 和 window onscroll 对我不起作用。文档 onclick 效果更好。
猜你喜欢
  • 2015-06-03
  • 1970-01-01
  • 1970-01-01
  • 2020-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-04
相关资源
最近更新 更多