nestjs-自定义装饰器

前面讲过通过 SetMetadata 装饰器 包装我们自己的装饰器,让其帮我们保存数据,然后再 guard中通过 context、reflector 获取该参数协助我们验权,也讲了通过 headers 装饰器包装我们的装饰器,终归限制很大,这里直接使用补充一个 createParamDecorator 创建我们自己的参数装饰器

先回顾一下我们使用 SetMetadata 封装的权限相关装饰器,

js 复制代码
//使用 SetMetadata 包装我们自己的装饰器
export const PUBLIC_KEY = '__public_key';
export const Public = () => SetMetadata(PUBLIC_KEY, PublicStatus.default);
//默认带token的,有user返回user
export const PublicUser = () => SetMetadata(PUBLIC_KEY, PublicStatus.token);


//在后续校验使用时,通过装饰器相关参数,获取到我们保存的数据
const publicStatus = this.reflector.getAllAndOverride<PublicStatus>(
  PUBLIC_KEY,
  [context.getHandler(), context.getClass()],
);

在回顾一下 Headers 装饰器包装的我们自己的装饰器,前面也说过,映射参数dto文档时,会把header里面加入的东西也映射出来,很不方便

js 复制代码
//设置一个key,方便快速通过装饰器获取用户信息,在jwt验证时存入,这里获取(由于header会映射出参数,使用request)
export const USER_ID_KEY  = '__user_id_key';
export const ReqUserId = () => Headers(USER_ID_KEY);

//如果保存的是 user 则可以用这个(由于header会映射出参数,使用request)
export const USER_KEY  = '__user_key';
export const ReqUser = () => Headers(USER_KEY);

//guard文件
canActivate(
    context: ExecutionContext,
  ): boolean {
    const request = context.switchToHttp().getRequest();
    let headers = request.headers
    const id=..., user=...
    //给我们的 headers 赋值,装饰器获取参数时,通过 Headers装饰器 取出
    headers[USER_ID_KEY] = id;
    headers[USER_KEY] = user;
  }
}

上面的Header装饰器包装的装饰器不太符合我们的要求,我们就通过 createParamDecorator包装一个适合我们的 User 装饰器 吧,其也不会被映射出来了

js 复制代码
//这里可以获取传递的参数,还有context
export const User = createParamDecorator(
    (data: string | undefined | null, ctx: ExecutionContext) => {
    //获取 request 
    const request = ctx.switchToHttp().getRequest();
    //鉴权时,如果登陆就保存一下user
    const user = request.user
    //外部装饰器传递参数,直接
    return data ? user?.[data] : user    
});
//我们的user的id就是id,直接传递id即可
export const ReqUserId = () => User('id');
//这里是为了兼容老写法,多加了一个,可以直接使用 @User
export const ReqUser = (key?: string | null) => User(key);

canActivate(
    context: ExecutionContext,
  ): boolean {
    const publicStatus = this.reflector.getAllAndOverride<PublicStatus>(
      PUBLIC_KEY,
      [context.getHandler(), context.getClass()],
    );
    
    const request = context.switchToHttp().getRequest();
    request[USER_KEY] = user;
  }
}

封装完毕,我们使用一下,记得别导入错了 User 类哈(有一个 UserEntity类)

js 复制代码
@ApiOperation({
    summary: '我的专栏',
})
@Post('features')
features(@User() user: User) {
    console.log(user)
}
相关推荐
Wang's Blog2 小时前
Nestjs框架: gRPC微服务通信及安全实践全解析
安全·微服务·架构·nestjs
Wang's Blog15 小时前
Nestjs框架: 微服务事件驱动通信与超时处理机制优化基于Event-Based 通信及异常捕获实践
微服务·云原生·架构·nestjs
Wang's Blog15 小时前
Nestjs框架: 微服务断路器实现原理与OPOSSUM库实践
运维·微服务·nestjs
Wang's Blog2 天前
Nestjs框架: 微服务容器化部署与网络通信解决方案
docker·微服务·云原生·架构·nestjs
濮水大叔2 天前
VonaJS业务抽象层: 验证码体系
typescript·nodejs·nestjs
代码哈士奇3 天前
Nestjs+nacos+kafka搭建中后台系统-后端(持续更新中)
redis·分布式·微服务·nacos·kafka·nestjs·pgsql
qq. 28040339845 天前
nestjs引篇
后端·node.js·nestjs
麻辣小蜗牛5 天前
深入理解 NestJS 内核:中间件 Middleware
nestjs
代码哈士奇7 天前
简单使用Nest+Nacos+Kafka实现微服务
后端·微服务·nacos·kafka·nestjs