Angular---怎样做鉴权

在开发web应用时,不可避免地要用到鉴权机制。那么,什么是鉴权呢?鉴权就是在应用中或应用的某一部分中,对用户身份进行权限鉴定,只有符合权限要求的用户才可以访问相应的内容。

鉴权的设计思路是这样的:

  • 在登录组件中,前端向后端提交数据,包括用户名和密码。
  • 后端验证成功后,返回给前端一个token值,用来唯一标识该用户。
  • 前端一般将这个token值存储在浏览器的cookie中,以备在鉴权时调用。当然存在session中也是可以的,具体要看应用的需求了。
  • 在路由配置中,给需要鉴权的模块添加路由守卫。

一个鉴权设计的例子

我们设计一个login组件和一个auth服务。其中auth服务颇为重要的。

这个auth服务一般包含下面几个方法:

  • canActivate()

用来做路由守护。

  • login()

用来处理登录操作。

  • logout()

用来处理注销操作。

  • setToken()

用来设置token。

  • getToken()

用来获取token。

  • removeToken()

用来删除token。

完整的auth服务的代码如下所示:

import { Inject, Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { CanActivate, Router } from '@angular/router';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class AuthService implements CanActivate {

  private headers = new HttpHeaders({
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
  });

  constructor(
    @Inject('BASE_CONFIG') private config,
    private http: HttpClient,
    private router: Router
  ) { }

  canActivate(): Observable<boolean> | boolean {
    if (document.cookie.indexOf('token=') > -1) {   // 如果能取到token,才可以跳转
      return true;
    } else {
      this.router.navigate(['/login']);  // 如果取不到token,跳转到登录页

      return false;
    }
  }

  login(data: any): Observable<any> {
    const param = "userName=" + data.userName + "&password=" + data.password;

    return this.http.post<any>('/labm/api/member/memberLogin', param, {headers: this.headers});
  }

  logout() {
    this.removeToken();
    this.router.navigate(['/']);  // 跳转到登录页
  }

  setToken(t: string) {
    document.cookie = `token=${t}`;
  }

  getToken() {
    let token = '';

    if (document.cookie) {
      let arr_cookie = document.cookie.split(';');
      let str_cookie_token = arr_cookie.filter(item => item.indexOf('token=') > -1);

      token = str_cookie_token[0].split('=')[1]
    } else {}

    return token;
  }

  removeToken() {
    document.cookie = "token=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
  }

}

login组件的模板是这样的:

<form [formGroup]="form" (ngSubmit)="onSubmit(form, $event)">
  <mat-card>
    <mat-card-header>
      <mat-card-title>
        <mat-icon>vpn_key</mat-icon>
        <span>欢迎登录</span>
      </mat-card-title>
    </mat-card-header>
    <mat-card-content>
      <mat-form-field>
        <input type="text" matInput placeholder="用户名" formControlName="userName">
        <mat-error>请填写用户名</mat-error>
      </mat-form-field>
      <mat-form-field>
        <input type="password" matInput placeholder="密码" formControlName="password">
        <mat-error>请填写密码</mat-error>
      </mat-form-field>
      <div class="buttonGroup">
        <a [routerLink]="[ '/']">取消</a>
        <button mat-flat-button color="primary" type="submit" [disabled]="!form.valid">登录</button>
      </div>
    </mat-card-content>
  </mat-card>
</form>

login组件的代码是这样的:

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { AuthService } from 'src/app/services/auth.service';

@Component({
  selector: 'yz-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {

  form: FormGroup;

  constructor(
    private fb: FormBuilder,
    private auth$: AuthService,
    private router: Router
  ) {
    if (this.auth$.getToken()) {  // 如果已经登录
      this.router.navigate(['/user']);
    } else {}
  }

  ngOnInit() {
    this.form = this.fb.group({
      userName: ['', Validators.required],
      password: ['', Validators.required]
    });
  }

  onSubmit({ value, valid }, ev: Event) {
    ev.preventDefault();

    if (valid) {
      this.auth$.login(value).subscribe(r => {
        if (r.success) {
          this.auth$.removeToken();
          this.auth$.setToken(r.data.token);
          this.router.navigate(['/user']);
        } else {
          window.alert(r.message);
        }
      });
    } else {}
  }

}

注意一下,在login组件中要引入auth服务:


在login组件中要引入auth服务.png

另外,在进行提交数据时,要先删除原有token值,然后再设置新值:


先删除,再设置.png

最后,在路由中给需要鉴权的模块添加路由守卫,比如给user模块添加:

给user模块添加路由守卫.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容