Angular8教程

Angular8 身份验证和授权

Authentication 是匹配 Web 应用程序访问者的过程具有系统中预定义的一组用户身份。换句话说,它是识别用户身份的过程。身份验证是系统中非常重要的过程,涉及安全性。
授权是授予用户访问系统中某些资源的权限的过程。只有经过身份验证的用户才能被授权访问资源。
让我们在本章中学习如何在 Angular 应用程序中进行身份验证和授权。

路由保护

在 Web 应用程序中,资源由 url 引用。系统中的每个用户都将被允许访问一组 url。例如,管理员可能会被分配到管理部分下的所有 url。
我们已经知道,URL 由 Routing 处理。 Angular 路由可以根据编程逻辑保护和限制 url。因此,普通用户可能会拒绝某个网址,而管理员可能会允许该网址。
Angular 提供了一个名为 Router Guards 的概念,可用于防止通过路由对应用程序的某些部分进行未经授权的访问。 Angular 提供了多个守卫,它们如下:
CanActivate-用于停止对路由的访问。 CanActivateChild-用于停止访问子路由。 CanDeactivate-用于停止从用户那里获取反馈的正在进行的过程。例如,如果用户回复是否定的,删除过程可以停止。 Resolve-用于在导航到路线之前预取数据。 CanLoad-用于加载资产。

工作示例

让我们尝试向我们的应用程序添加登录功能并使用 CanActivate 保护来保护它。
打开命令提示符并转到项目根文件夹。
cd /go/to/expense-manager
启动应用程序。
ng serve
创建一个新服务 AuthService 以对用户进行身份验证。
ng generate service auth
CREATE src/app/auth.service.spec.ts (323 bytes)
CREATE src/app/auth.service.ts (133 bytes)
打开 AuthService 并包含以下代码。
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { tap, delay } from 'rxjs/operators';
@Injectable({
   providedIn: 'root'
})
export class AuthService {
   isUserLoggedIn: boolean = false;
   login(userName: string, password: string): Observable
    
   
    
      {
      console.
    log(userName);
      console.
    log(password);
      
    this.isUserLoggedIn = userName == 
    'admin' && password == 'admin';
      localStorage.
    setItem(
    'isUserLoggedIn', 
    this.isUserLoggedIn ? 
    "true" : 
    "false"); 
   
    return of(
    this.
    isUserLoggedIn).pipe(
      delay(1000),
      tap(val => { 
         console.
    log(
    "Is User Authentication is successful: " + val); 
      })
   );
   }
   logout():
     void {
   
    this.isUserLoggedIn =
     false;
      localStorage.
    removeItem('isUserLoggedIn'); 
   }
   constructor() { }
}
    
   
这里,
我们编写了两个方法,loginlogout login 方法的目的是验证用户,如果用户验证成功,它会将信息存储在 localStorage 中,然后返回 true。 身份验证是用户名和密码应该是admin。 我们没有使用任何后端。相反,我们使用 Observables 模拟了 1 秒的延迟。 logout 方法的目的是使用户无效并删除存储在 localStorage 中的信息。
使用以下命令创建一个 login 组件-
ng generate component login
CREATE src/app/login/login.component.html (20 bytes)
CREATE src/app/login/login.component.spec.ts (621 bytes)
CREATE src/app/login/login.component.ts (265 bytes)
CREATE src/app/login/login.component.css (0 bytes)
UPDATE src/app/app.module.ts (1207 bytes)
打开 LoginComponent 并包含以下代码-
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
import { AuthService } from '../auth.service';
import { Router } from '@angular/router';
@Component({
   selector: 'app-login',
   templateUrl: './login.component.html',
   styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
   userName: string;
   password: string;
   formData: FormGroup;
   constructor(private authService : AuthService, private router : Router) { }
   ngOnInit() {
      this.formData = new FormGroup({
         userName: new FormControl("admin"),
         password: new FormControl("admin"),
      });
   }
   onClickSubmit(data: any) {
      this.userName = data.userName;
      this.password = data.password;
      console.log("Login page: " + this.userName);
      console.log("Login page: " + this.password);
      this.authService.login(this.userName, this.password)
         .subscribe( data => { 
            console.log("Is Login Success: " + data); 
      
           if(data) this.router.navigate(['/expenses']); 
      });
   }
}
这里,
使用反应式形式。 导入 AuthService 和 Router 并在构造函数中进行配置。 创建了一个 FormGroup 实例并包含两个 FormControl 实例,一个用于用户名,另一个用于密码。 创建了一个 onClickSubmit 以使用 authService 验证用户,如果成功,则导航到费用列表。
打开 LoginComponent 模板并包含以下模板代码。
<!--Page Content-->
<div class="container">
   <div class="row">
      <div class="col-lg-12 text-center" style="padding-top: 20px;">
         <div class="container box" style="margin-top: 10px; padding-left: 0px; padding-right: 0px;">
            <div class="row">
               <div class="col-12" style="text-align: center;">
                                    <form [formGroup]="formData" (ngSubmit)="onClickSubmit(formData.value)" 
                                          class="form-signin">
                                    <h2 class="form-signin-heading">Please sign in</h2>
                                    <label for="inputEmail" class="sr-only">Email address</label>
                                    <input type="text" id="username" class="form-control" 
                                          formControlName="userName" placeholder="Username" required autofocus>
                                    <label for="inputPassword" class="sr-only">Password</label>
                                    <input type="password" id="inputPassword" class="form-control" 
                                          formControlName="password" placeholder="Password" required>
                                    <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
                                    </form>
               </div>
            </div>
         </div>
      </div>
   </div>
</div>
这里,
创建了一个响应式表单并设计了一个登录表单。
onClickSubmit 方法附加到表单提交操作。
打开 LoginComponent 样式并包含以下 CSS 代码。
.form-signin {
   max-width: 330px;
   padding: 15px;
   margin: 0 auto;
}
input {
   margin-bottom: 20px;
}
这里添加了一些样式来设计登录表单。
使用以下命令创建注销组件-
ng generate component logout
CREATE src/app/logout/logout.component.html (21 bytes)
CREATE src/app/logout/logout.component.spec.ts (628 bytes)
CREATE src/app/logout/logout.component.ts (269 bytes)
CREATE src/app/logout/logout.component.css (0 bytes)
UPDATE src/app/app.module.ts (1368 bytes)
打开 LogoutComponent 并包含以下代码。
import { Component, OnInit } from '@angular/core';
import { AuthService } from '../auth.service';
import { Router } from '@angular/router';
@Component({
   selector: 'app-logout',
   templateUrl: './logout.component.html',
   styleUrls: ['./logout.component.css']
})
export class LogoutComponent implements OnInit {
   constructor(private authService : AuthService, private router: Router) { }
   ngOnInit() {
      this.authService.logout();
      this.router.navigate(['/']);
   }
}
这里,
使用了 AuthService 的注销方法。 一旦用户注销,页面将重定向到主页 (/)。
使用以下命令创建守卫-
ng generate guard expense
CREATE src/app/expense.guard.spec.ts (364 bytes)
CREATE src/app/expense.guard.ts (459 bytes)
打开 ExpenseGuard 并包含以下代码-
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from './auth.service';
@Injectable({
   providedIn: 'root'
})
export class ExpenseGuard implements CanActivate {
   constructor(private authService: AuthService, private router: Router) {}
   canActivate(
   next: ActivatedRouteSnapshot,
   state: RouterStateSnapshot): boolean | UrlTree {
      let url: string = state.url;
          return this.checkLogin(url);
      }
      checkLogin(url: string): true | UrlTree {
         console.log("Url: " + url)
         let val: string = localStorage.getItem('isUserLoggedIn');
         if(val != null && val == "true"){
            if(url == "/login")
               this.router.parseUrl('/expenses');
            else 
               return true;
         } else {
            return this.router.parseUrl('/login');
         }
      }
}
这里,
checkLogin 将检查 localStorage 是否有用户信息,如果可用,则返回 true。 如果用户登录并进入登录页面,它会将用户重定向到费用页面 如果用户未登录,则用户将被重定向到登录页面。
打开 AppRoutingModule (src/app/app-routing.module.ts) 并更新以下代码-
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { ExpenseEntryComponent } from './expense-entry/expense-entry.component';
import { ExpenseEntryListComponent } from './expense-entry-list/expense-entry-list.component';
import { LoginComponent } from './login/login.component';
import { LogoutComponent } from './logout/logout.component';
import { ExpenseGuard } from './expense.guard';
const routes: Routes = [
   { path: 'login', component: LoginComponent },
   { path: 'logout', component: LogoutComponent },
   { path: 'expenses', component: ExpenseEntryListComponent, canActivate: [ExpenseGuard]},
   { path: 'expenses/detail/:id', component: ExpenseEntryComponent, canActivate: [ExpenseGuard]},
   { path: '', redirectTo: 'expenses', pathMatch: 'full' }
];
@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
这里,
导入的 LoginComponent 和 LogoutComponent。 导入的 ExpenseGuard。 创建了两个新路由,login 和 logout 分别访问 LoginComponent 和 LogoutComponent。 为 ExpenseEntryComponent 和 ExpenseEntryListComponent 添加新选项 canActivate。
打开 AppComponent 模板并添加两个登录和注销链接。
<div class="collapse navbar-collapse" id="navbarResponsive">
   <ul class="navbar-nav ml-auto">
      <li class="nav-item active">
         <a class="nav-link" href="#">Home
            <span class="sr-only" routerLink="/">(current)</span>
         </a>
      </li>
      <li class="nav-item">
         <a class="nav-link" routerLink="/expenses">Report</a>
      </li>
      <li class="nav-item">
         <a class="nav-link" href="#">Add Expense</a>
      </li>
      <li class="nav-item">
         <a class="nav-link" href="#">About</a>
      </li>
      <li class="nav-item">
                  <div *ngIf="isUserLoggedIn; else isLogOut">
                        <a class="nav-link" routerLink="/logout">Logout</a>
                  </div>
                  <ng-template #isLogOut>
                              <a class="nav-link" routerLink="/login">Login</a>
                  </ng-template>
      </li>
   </ul>
</div>
打开 AppComponent 并更新以下代码-
import { Component } from '@angular/core';
import { AuthService } from './auth.service';
@Component({
   selector: 'app-root',
   templateUrl: './app.component.html',
   styleUrls: ['./app.component.css']
})
export class AppComponent {
   title = 'Expense Manager';
   isUserLoggedIn = false;
   constructor(private authService: AuthService) {}
   ngOnInit() {
      let storeData = localStorage.getItem("isUserLoggedIn");
      console.log("StoreData: " + storeData);
      if( storeData != null && storeData == "true")
         this.isUserLoggedIn = true;
      else
         this.isUserLoggedIn = false;
   }
}
在这里,我们添加了识别用户状态的逻辑,以便我们可以显示登录/注销功能。
打开 AppModule (src/app/app.module.ts) 并配置 ReactiveFormsModule
import { ReactiveFormsModule } from '@angular/forms'; 
imports: [ 
   ReactiveFormsModule 
]
现在,运行应用程序,应用程序打开登录页面。
ReactiveFormsModule
输入 admin 和 admin 作为用户名和密码,然后点击提交。应用程序处理登录并将用户重定向到费用列表页面,如下所示-
FormsModule
最后,您可以单击注销并退出应用程序。
昵称: 邮箱:
Copyright © 2022 立地货 All Rights Reserved.
备案号:京ICP备14037608号-4