Auth.guard.ts

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable()
export class AuthGuard implements CanActivate {
    canActivate(
        context: ExecutionContext,
    ): boolean | Promise<boolean> | Observable<boolean> {
        console.log('守卫执行了');
        // return true;
        // 模拟做权限判断
        var n = Math.random();
        console.log('n: ', n);
        if(n>0.5){
            return true;
        return false;

二、守卫的简单使用

1.直接加在控制器上,这个控制器下所有的路由都要走守卫

在模块分支上做演示,admin/controller/user/user.controller.ts

// 使用守卫1:引入UseGuards
import { Controller, Get, UseGuards, UsePipes } from '@nestjs/common';
// 使用守卫2:引入自定义的守卫
import { AuthGuard } from '../../../../guard/auth.guard'
@Controller('admin/user')
// 使用守卫3.1:守卫可以直接加在控制器上面,整个控制器下所有方法都需要进行权限判断
@UseGuards(AuthGuard)
export class UserController {
    @Get()
    index() {
        return '我是admin模块里的user控制器';

2.加在具体的方法上

在admin/controller/news/news.controller.ts

// 使用守卫1:引入UseGuards
import { Controller, Get, UseGuards, UsePipes } from '@nestjs/common';
// 使用守卫2:引入自定义的守卫
import { AuthGuard } from '../../../../guard/auth.guard'
@Controller('admin/news')
export class NewsController {
    @Get()
    index() {return 'admin-news路由';}
    @Get('list') 
    newsList() {
        return '查看新闻列表不需要守卫';
    @Get('add') 
    // 使用守卫3.2:守卫可用在控制器的具体方法上
    @UseGuards(AuthGuard)
    addNews() {
        return '新增新闻要守卫';

三、全局守卫

在main.ts中配置

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
// 全局守卫1: 引入
import { AuthGuard } from './guard/auth.guard'
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  // 全局守卫2: 配置
  app.useGlobalGuards(new AuthGuard());
  await app.listen(3000);
bootstrap();

注:全局配置后,访问所有的路由都要经过守卫鉴权。

四、全局守卫结合cookie和session做接口校验

实战思路:

  • 访问login生成session

  • 访问其他路由时校验是否有session,模拟前端判断是否登录的业务

1.main.ts中引入cookie和session,配置全局守卫

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as cookieParser from 'cookie-parser';
import * as session from 'express-session';
// 全局守卫1: 引入
import { AuthGuard } from './guard/auth.guard'
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.use(cookieParser('this signed cookies'));
  app.use(session(
      secret: 'keyboard cat',  // 秘钥
      cookie: { maxAge: 10000*60*60 } //session的存储时间
  // 全局守卫2: 配置
  app.useGlobalGuards(new AuthGuard());
  await app.listen(3000);
bootstrap();

2.守卫auth.guard.ts

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable()
export class AuthGuard implements CanActivate {
    canActivate(
        context: ExecutionContext,
    ): boolean | Promise<boolean> | Observable<boolean> {
        console.log('守卫执行了');
        // 在守卫中获取session 
        let req = context.switchToHttp().getRequest();
        console.log('req: ', req.path);
        // 访问某些路由时不检验是否登录
        if(req.path == '/admin/login') {
            return true;
        }else {
            // 实际业务,可以用来判断是否登录,是否有权限访问数据接口;
            let userInfo = context.switchToHttp().getRequest().session.username;
            console.log('在守卫中获取session: ', userInfo);
            if(userInfo) { 
                console.log('通过路由守卫');
                return true 
            return false;

3.login.controller.ts

import { Controller, Get,Request } from '@nestjs/common';
@Controller('admin/login')
export class LoginController {
    @Get()
    index(@Request() req) {
        // 登录 设置session
        req.session.username = '张三';
        return '登录成功';
    // 测试是否有session
    @Get('getSession') 
    getSession(@Request() req) {
        return req.session.username;

4.浏览器校验

1.访问login模拟登录,生成session
	http://localhost:3000/admin/login
2.访问其他接口,让守卫判断是否登录
	http://localhost:3000/admin/news
```typescript
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Observa
                                    守卫有一个单独的责任。它们根据运行时出现的某些条件(例如权限,角色,访问控制列表等)来确定给定的请求是否由路由处理程序处理。guard  使用  Reflector 反射读取 setMetaData的值 去做判断这边例子是从url 判断有没有admin权限。应用程序中,通常由中间件处理授权(以及认证)。中间件是身份验证的良好选择,因为诸如。tips 守卫在每个中间件之后执行,但在任何拦截器或管道之前执行。第一个参数为key,第二个参数自定义我们的例子是数组存放的权限。SetMetadata 装饰器。
                                    从客户端发送一个post请求,路径为:/user/userAdd,请求参数为:{userinfo: ‘xx’,password: ‘xx’},到服务器接收请求内容,触发绑定的函数后执行相关逻辑完毕,然后返回内容的整个过程大体上要经过如下几个步骤:
明天要测试中间件、守卫、管道、异常过滤器、拦截器各个阶段的顺序问题以及错误抛出问题,总结挂载问题,对应的解决问题