jes*_*ial 10 javascript decorator node.js typescript nestjs
I want to achieve something like this using nest.js: (something very similar with Spring framework)
@Controller('/test')
class TestController {
@Get()
get(@Principal() principal: Principal) {
}
}
Run Code Online (Sandbox Code Playgroud)
After hours of reading documentation, I found that nest.js supports creating custom decorator. So I decided to implement my own @Principal decorator. The decorator is responsible for retrieving access token from http header and get principal of user from my own auth service using the token.
import { createParamDecorator } from '@nestjs/common';
export const Principal = createParamDecorator((data: string, req) => {
const bearerToken = req.header.Authorization;
// parse.. and call my authService..
// how to call my authService here?
return null;
});
Run Code Online (Sandbox Code Playgroud)
But the problem is that I have no idea how to get my service instance inside a decorator handler. Is it possible? And how? Thank you in advance
Kim*_*ern 16
无法将服务注入您的自定义装饰器。
相反,您可以创建一个AuthGuard可以访问您的服务的对象。然后守卫可以向request对象添加一个属性,然后您可以使用自定义装饰器访问该属性:
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const bearerToken = request.header.Authorization;
const user = await this.authService.authenticate(bearerToken);
request.principal = user;
// If you want to allow the request even if auth fails, always return true
return !!user;
}
}
Run Code Online (Sandbox Code Playgroud)
import { createParamDecorator } from '@nestjs/common';
export const Principal = createParamDecorator((data: string, req) => {
return req.principal;
});
Run Code Online (Sandbox Code Playgroud)
然后在您的控制器中:
@Get()
@UseGuards(AuthGuard)
get(@Principal() principal: Principal) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
请注意,nest 提供了一些用于身份验证的标准模块,请参阅文档。
小智 16
对于 NestJS v7
创建自定义管道
// parse-token.pipe.ts
import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common';
import { AuthService } from './auth.service';
@Injectable()
export class ParseTokenPipe implements PipeTransform {
// inject any dependency
constructor(private authService: AuthService) {}
async transform(value: any, metadata: ArgumentMetadata) {
console.log('additional options', metadata.data);
return this.authService.parse(value);
}
}
Run Code Online (Sandbox Code Playgroud)
将此管道与属性装饰器一起使用
// decorators.ts
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { ParseTokenPipe} from './parse-token.pipe';
export const GetToken = createParamDecorator((data: unknown, ctx: ExecutionContext) => {
return ctx.switchToHttp().getRequest().header.Authorization;
});
export const Principal = (additionalOptions?: any) => GetToken(additionalOptions, ParseTokenPipe);
Run Code Online (Sandbox Code Playgroud)
在有或没有附加选项的情况下使用此装饰器
@Controller('/test')
class TestController {
@Get()
get(@Principal({hello: "world"}) principal) {}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5922 次 |
| 最近记录: |