【NestJS】Guard 守卫


守卫一般用于授权处理,判断当前请求是否能放行给路由处理程序。

执行顺序:中间件 - 守卫 - 拦截器 / 管道



使用守卫

  1. 创建 CRUD 模板:nest g res cus-guard
  2. 创建守卫:nest g gu cus-guard
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Observable } from 'rxjs';

@Injectable() // 守卫也是使用 @Injectable() 修饰;  需要继承自 CanActivate
export class CusGuardGuard implements CanActivate {
    // 需要实现 canActivate 方法;  该方法接收参数 ctx, 返回布尔值
    canActivate(
        context: ExecutionContext,
    ): boolean | Promise<boolean> | Observable<boolean> {
        console.log('经过了守卫');
        return true; // 返回 truely 值表示放行, 否则当前请求会被拦截
    }
}
  1. 通过 @UseGuards(XXX) 装饰器使用守卫
import { Controller, Get, UseGuards } from '@nestjs/common';
import { CusGuardGuard } from './cus-guard.guard';
import { CusGuardService } from './cus-guard.service';

@Controller('cus-guard')
@UseGuards(CusGuardGuard) // 使用守卫
export class CusGuardController {
    constructor(private readonly cusGuardService: CusGuardService) {}

    @Get()
    findAll() {
        return this.cusGuardService.findAll();
    }
}

如果需要使用多个守卫,可以给 UseGuards 传入多个参数:@UseGuards(XXX, XXX, XXX)。守卫会从左往右执行。若前面的守卫没有放行,则不会执行后面的守卫。


也可以把守卫放到指定方法前,表示只有这个方法需要鉴权

@Controller('cus-guard')
export class CusGuardController {
    constructor(private readonly cusGuardService: CusGuardService) {}

    @Get()
		@UseGuards(CusGuardGuard) // 使用守卫
    findAll() {
        return this.cusGuardService.findAll();
    }
}



全局守卫

  1. 创建守卫:nest g gu cus-guard
  2. 使用 useGlobalGuards 注册全局守卫
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { CusGuardGuard } from './cus-guard/cus-guard.guard'; // 引入守卫

async function bootstrap() {
    const app = await NestFactory.create(AppModule);
    app.useGlobalGuards(new CusGuardGuard()); // 注册全局守卫
    await app.listen(3000);
}
bootstrap();



配置角色权限

  1. 使用装饰器 @SetMetadata(key, value) 配置角色
import { Controller, Get, UseGuards, SetMetadata } from '@nestjs/common';
import { CusGuardGuard } from './cus-guard.guard';
import { CusGuardService } from './cus-guard.service';

@Controller('cus-guard')
@UseGuards(CusGuardGuard)
export class CusGuardController {
    constructor(private readonly cusGuardService: CusGuardService) {}

    @Get()
    @SetMetadata('role', ['admin']) // 注入数据
    findAll() {
        return this.cusGuardService.findAll();
    }
}
  1. 使用反射 Reflector 读取 SetMetadata 的值
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Observable } from 'rxjs';

@Injectable()
export class CusGuardGuard implements CanActivate {
    constructor(private reflector: Reflector) {} // 注入 Reflector 实例

    canActivate(
        context: ExecutionContext,
    ): boolean | Promise<boolean> | Observable<boolean> {
        // 通过 Reflector 实例的 get 方法获取被注入的数据
        const role = this.reflector.get<string[]>('role', context.getHandler());
        console.log('role', role);
        return true;
    }
}

现在请求 /cus-guard 会在服务端打印 role [ 'admin' ]


假设我们通过 query 参数携带权限信息,我们需要根据该权限信息进行授权:

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Request } from 'express';
import { Observable } from 'rxjs';

@Injectable()
export class CusGuardGuard implements CanActivate {
    constructor(private reflector: Reflector) {}

    canActivate(
        context: ExecutionContext,
    ): boolean | Promise<boolean> | Observable<boolean> {
        const role = this.reflector.get<string[]>('role', context.getHandler());
        const req = context.switchToHttp().getRequest<Request>(); // 获取请求
        const cusRole = req.query.role as string; // 获取 query 参数 role
        const permission = role.includes(cusRole); // 判断权限
        console.log('permission', permission);
        return permission;
    }
}

img


不携带 query 参数 role / role 值不为 'admin',都会抛出 403 ( Forbidden referer origin )

img

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JS.Huang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值