在Angular 12中实现自动注销
自动注销是Web开发和移动应用中一个普遍存在的功能,特别是在银行系统中。因此,它在确保数据的安全性和完整性方面发挥着重要作用。
自动注销的用处在于,应用程序的用户在使用后可能会忘记注销系统。
本教程讨论了我们如何建立一个安全的Angular应用程序,可以签出闲置的屏幕。
先决条件
要跟上进度,你需要具备以下条件。
- 具备JavaScript或TypeScript的基本知识
- 基本的Angular概念
- 了解Node Package Manager(NPM)的概念。
教学目的
本教程的目的是教给你一切你所需要的Angular应用安全入门知识。
我们将建立一个能自动注销用户的认证应用样本。
开始使用自动注销
自动注销是一项安全功能,它决定了一个屏幕可以保持空闲的时间。简单地说,它是指一个屏幕在没有用户操作(如点击事件)的情况下保持活动的时间。
这个功能在资源管理和安全方面是非常核心的。
在资源管理方面,它有助于停止不必要的API调用,并最大限度地减少受攻击的可能性。
设置一个自动注销项目的样本
让我们在Angular 12中建立一个示例应用程序,实现自动注销的功能。
让我们从安装一个Angular应用程序开始,如下图所示。
ng new sample-auto-logout
这个命令安装了一个Angular应用程序sample-auto-logout ,其中包含所有需要的依赖。
接下来,cd ,进入这个项目根目录,并创建以下组件。
cd sample-auto-logout
ng g component auth/sign-in
ng g component auth/create-account
上面的命令在auth 目录内创建了2个组件,signInComponent 和CreateAccountComponent 。
安装软件包
在这个应用程序中,我们将使用Angular材料来设计我们的网页,以及使用Snotify包来显示警报。
让我们通过运行以下命令将它们添加到我们的Angular应用程序中。
npm i ng-snotify # for NPM users or
yarn add ng-snotify #for yarn
如果你是第一次使用
snotify,请随时在这里浏览它的文档。或者,你也可以使用Toast通知。让这些警报服务在屏幕上通知用户他们已经注销了,这很重要。
让我们继续通过运行以下命令来添加Angular Material 。
ng add @angular/material
这提示了快速的是/否问题。
一旦完成,你就可以把所需的模块导入到app.module.ts ,这将在接下来的步骤中解释。
创建认证表格
现在我们的应用程序已经有了auth组件,在CreateAccountComponent 模板中添加以下内容。
<div class="citizen-registration">
<div class="container">
<mat-card class="mt-5 mb-5">
<mat-card-title class="text-center">Register</mat-card-title>
<mat-card-content class="justify-content-center">
<form
[formGroup]="citizenRegistrationForm"
(ngSubmit)="onCitizenRegistration()"
novalidate
role="form"
>
<input type="hidden" formControlName="role" value="citizen" />
<p>
<mat-form-field appearance="standard" color="primary">
<mat-label>Full Name</mat-label>
<input
matInput
placeholder="Ezekiel Alawode"
required
name="fullName"
formControlName="fullName"
autocomplete="fullName"
/>
<mat-icon matSuffix>account_circle</mat-icon>
</mat-form-field>
</p>
<p>
<mat-form-field appearance="standard">
<mat-label>Town/City</mat-label>
<input
matInput
placeholder="Okene"
required
formControlName="city"
name="city"
autocomplete="city"
/>
</mat-form-field>
</p>
<p>
<mat-form-field appearance="standard">
<mat-label>Phone</mat-label>
<input
type="tel"
matInput
placeholder="08143651284"
required
name="phone"
formControlName="phone"
autocomplete="phone"
/>
</mat-form-field>
</p>
<p>
<mat-form-field appearance="standard">
<mat-label>Email Address</mat-label>
<input
type="tel"
matInput
placeholder="johndoe@example.com"
required
name="email"
formControlName="email"
autocomplete="email"
/>
</mat-form-field>
</p>
<p>
<mat-form-field appearance="standard">
<mat-label>Password</mat-label>
<input
type="password"
matInput
required
name="password"
formControlName="password"
autocomplete="password"
/>
</mat-form-field>
</p>
<p>
<mat-checkbox class="example-margin"
>I agree with the <a href="#">Terms and Conditions</a>, governing
this site.</mat-checkbox
>
</p>
<div class="row mt-5">
<div class="col-md-6">
<button *ngIf="!submitting" type="submit" class="register-button">
Register
</button>
<button *ngIf="submitting" type="submit" class="register-button">
Processing...
</button>
</div>
<div class="col-md-6">
<a class="login-button text-right" [routerLink]="['/auth/login']"
>Login Here</a
>
</div>
</div>
</form>
</mat-card-content>
</mat-card>
</div>
</div>
上面的模板是一个组织的注册表格样本,公司在其中捕获了用户的详细信息。
这个HTML页面使用Angular材料,通过运行以下命令添加。
ng add @angular/material
这个命令会提示你回答基本的是/否问题,这有助于材料的定制。
我们需要从之前安装的软件包中导入一些模块,以便我们上面的模板能够工作。
最简单的方法是在src/app 目录中创建一个新的模块来实现。
ng g module app-material
现在继续更新这个模块的内容,添加以下内容。
import { NgModule } from "@angular/core";
import { MatCardModule } from "@angular/material/card";
import { MatCheckboxModule } from "@angular/material/checkbox";
@NgModule({
exports: [MatCardModule, MatCheckboxModule],
})
export class DemoMaterialModule {}
接下来,把这个模块导入到app.module.ts 文件中,如下图所示。
...
import {MaterialModule} from "./material-module";
@NgModule({
declarations: [
AppComponent,
SignInComponent,
CreateAccountComponent,
],
imports: [
...
AppRoutingModule,
],
providers: [ ],
bootstrap: [AppComponent]
})
export class AppModule { }
在上面的模块中,我们声明了我们之前创建的组件,然后导入材料模块。
现在,让我们添加一些样式来美化我们的页面。
mat-form-field {
font-size: 16px;
}
mat-card-title {
font-family: Poppins;
font-style: normal;
font-weight: bolder;
font-size: 40px;
line-height: 60px;
text-align: center;
color: #ffffff;
}
mat-form-field {
width: 100%;
color: #ffffff;
}
mat-card {
width: 525px;
height: auto;
left: auto;
top: auto;
margin: 0 auto;
background: #c60c5a;
box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.6);
border-radius: 5px;
}
mat-label {
font-family: Poppins;
font-style: normal;
font-weight: bold;
font-size: 24px;
line-height: 36px;
color: #ffffff;
}
mat-form-field input {
padding: 5px;
color: #ffffff;
}
mat-icon {
color: #ffffff;
}
mat-checkbox {
color: #ffffff;
}
.register-button {
width: 194px;
height: 45px;
background: #004598;
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.5);
border-radius: 3px;
font-family: "Poppins", sans-serif;
font-style: normal;
font-weight: 600;
font-size: 16px;
line-height: 24px;
text-align: center;
color: #ffffff;
}
.login-button {
font-family: "Poppins", sans-serif;
font-style: normal;
font-weight: normal;
font-size: 18px;
line-height: 27px;
text-align: right;
text-decoration-line: underline;
color: #ffffff;
}
我们在上面的样式文件中用我们定义的CSS样式编辑默认的Angular material表单。当然,你可以自由定制,以满足你的需求。
输出。

如何确定一个屏幕是否闲置
现在我们有了一个完整的认证表单,让我们来确定用户的屏幕是否处于闲置状态。
这个工作非常简单,我们跟踪用户在网络应用上的操作。值得注意的是,这些行动相当于事件。
当用户在应用程序上采取行动时,我们将其作为一个行动记录在浏览器的本地存储中。
每当用户采取行动时,我们就重置本地存储中的时钟并重新开始计数。然后这个时钟与本地时间同步,以进行适当的改变。
让我们创建一个服务AutoLogOffService ,并添加以下代码。
...
@Injectable({
providedIn: 'root'
})
export class AutoLogoutService {
//log off details
isLogin = false;
constructor(
private router: Router,
private snotifyService: SnotifyService,
private ngZone: NgZone
) {
if(this.isUserLoggedIn()){
this.isLogin=true;
}
this.lastAction(Date.now());
this.check();
this.initListener();
this.initInterval();
}
/**
* last action
*/
getLastAction() {
return localStorage.getItem('lastAction');
}
/**
* set last action
* @param value
*/
lastAction(value) {
localStorage.setItem('lastAction', JSON.stringify(value))
}
/**
* start event listener
*/
initListener() {
this.ngZone.runOutsideAngular(() => {
document.body.addEventListener('click', () => this.reset());
});
}
/**
* time interval
*/
initInterval() {
this.ngZone.runOutsideAngular(() => {
setInterval(() => {
this.check();
}, 1000);
})
}
/**
* reset timer
*/
reset() {
this.lastAction(Date.now());
}
/**
* check timer
*/
check() {
const now = Date.now();
const timeLeft = parseInt(this.getLastAction()) + (5) * 60 * 1000;
const diff = timeLeft - now;
const isTimeout = diff < 0;
//this.isLoggedIn.subscribe(event => this.isLogin = event);
this.ngZone.run(() => {
if (isTimeout && this.isLogin) {
localStorage.removeItem('user_id');
localStorage.removeItem('lastAction');
setTimeout(()=>{
console.log("Your Session Expired due to longer Inactivity, Login Again To Continue");
},10000);
this.router.navigate(['login']);
}
});
}
/**
*check if a user is logged in
*/
isUserLoggedIn():string{
return environment.authKey;
}
}
上面的代码有一个时间间隔和事件监听器;因此我们可以根据需要设置自动注销时间。
让我们看看每个步骤,深入了解它是如何工作的。
isLogin = false- 这是一个布尔属性,用于检查用户是否已登录。constructor()- 构造器注入了3个服务。router- 这是我们用来在用户被自动注销时将其重定向到登录页面的服务。它是Angular的一个内置工具。snotifyService-Snotify是第三方软件包,用于在不破坏用户界面的情况下在屏幕上显示警报。NgZone- NgZone使我们能够明确地在Angular的Zone之外运行某些代码,防止Angular运行任何变化检测。处理程序仍然会被执行。然而,由于它们不会在Angular的区域内运行,Angular不会得到任务完成的通知。因此,不会有任何变化检测被执行。
if statement- 在构造函数中,我们要检查用户是否真的登录了。getLastAction()- 我们用这个方法来获取当前用户与应用程序交互的最新时间。重要的是要记住,我们必须通过重设我们的时钟来跟踪应用程序上的每一个事件,试图获得最新的行动。lastAction(value)- 这是一个简单的方法,在每次事件发生时,在本地存储中设置我们的时钟。initListener()- 之前,我们已经说过,我们正在跟踪用户在应用程序上的活动。它监听应用程序上的每个动作;在我们的例子中,我们监听的是 事件。每次有 事件发生时,这个方法都会重置我们在本地存储中的时钟。clickclickinitInterval()- 这个方法初始化检查点击事件的时间间隔;这完全取决于你想如何跟踪这些情况;在我们的例子中,我们将时间间隔设置为每秒(1000ms=1s)。reset()- 这个方法通过调用 方法并传递给它当前的日期来重置最后一个动作的时钟。lastAction()check()- 这个方法检查定时器。例如,它计算出当前时间和上一个动作的时间之间的差异。然后,这个差值被用来决定用户是应该注销还是保持会话状态。事实上,正是在这个方法上,我们设置了一个屏幕应该保持不活动的时间。在我们的案例中,我们将其设置为 分钟。当然,你可以把它设置为你希望的任何时间。5isUserLoggedIn()- 这个方法通过检查认证令牌来检查用户是否已经登录。然而,这完全由你来决定如何认证用户。
我们实现的问题
在上一节中,你已经看到了如何使用Angular实现自动注销。然而,你可能已经注意到一些设定的时间间隔。
对于我们的应用程序来说,自动注销一个空闲的屏幕,它必须运行一些检查并跟踪每一个动作。这可能会耗费资源。
总结
在本教程中,我们已经介绍了Angular应用程序中自动注销的概念。
我们已经看到,我们可以使用事件监听器来跟踪我们应用程序上的活动,这有助于确定行动。