注:此文仅记录博主初次学习nestjs之后的认识和理解,经验尚浅,文章内容仅供参考,如若有误,敬请指正。
作为切面
此文暂不对细节展开探讨
1.切面类型:CanActivate接口实现类
2.切面输入
ExecutionContext对象:执行上下文对象,继承至参数主机对象ArgumentsHost
此文关注点不在ExecutionContext对象,在此不做细节探讨。
export interface ExecutionContext extends ArgumentsHost {
getClass<T = any>(): Type<T>;
getHandler(): Function;
}
3.切面输出:继续请求 or 返回响应
- return boolean | Promise | Observable
4.切面使用场景
- 权限管理
权限管理案例
权限管理可通过守卫技术实现,守卫之名顾名思义,可负责鉴权,符合权限的请求通过,不符合的直接响应。
1.给控制器绑定权限(给门贴上通过规则)
- 自定义元数据装饰器
// 自定义权限装饰器,@SetMetadata()装饰器拥有将定制元数据附加到路由处理程序的能力,可用于控制器绑定权限以便读取
import {
SetMetadata } from '@nestjs/common';
export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
- 使用元数据装饰器
@Post()
// @SetMetadata('roles', ['admin']) // 方式1:使用@SetMetadata装饰器
@Roles('admin') // 方式2:使用自定义装饰器封装@SetMetadata装饰器
async create(@Body() createCatDto: CreateCatDto) {
this.catsService.create(createCatDto);
}
2.给控制器绑定守卫者(给门分配站岗门卫)
- 定义守卫者
import {
Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import {
Reflector } from '@nestjs/core';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {
}
canActivate(context: ExecutionContext): boolean {
const roles = this.reflector.get<string[]>('roles', context.getHandler());
if (!roles) {
return true;
}
const request = context.switchToHttp().getRequest();
const user = request.user;
return matchRoles(roles, user.roles);
}
}
- 绑定守卫者
// 方式1:方法守卫(controller上)
@UseGuards(new RolesGuard())
// 方式2:全局守卫(app.module.ts)
@Module({
providers: [
{
provide: APP_GUARD,
useClass: RolesGuard,
},
],
})
3.守卫者鉴权失败(被门卫叉刀拦下)
- 默认响应
{
"statusCode": 403,
"message": "Forbidden resource"
}
- 自定义响应
// 守卫者抛出异常
throw new UnauthorizedException();