前面讲过通过 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
类哈(有一个 User
的 Entity
类)
js
@ApiOperation({
summary: '我的专栏',
})
@Post('features')
features(@User() user: User) {
console.log(user)
}