gpt4 book ai didi

javascript - NestJS:使用 JWT 向 AuthGuard 添加验证选项

转载 作者:搜寻专家 更新时间:2023-10-31 23:44:44 26 4
gpt4 key购买 nike

我正在尝试使用 AuthGuard 装饰器和 passport JWT 策略,遵循 documentation .

文档中的所有内容都很好用。但是我现在想保护一个范围包含在 JWT 中的路由。所以这是我的应用程序生成的基本 jwt 有效负载:

{
"user": {
"id": "20189c4f-1183-4216-8b48-333ddb825de8",
"username": "user.test@gmail.com"
},
"scope": [
"manage_server"
],
"iat": 1534766258,
"exp": 1534771258,
"iss": "15f2463d-8810-44f9-a908-801872ded159",
"sub": "20189c4f-1183-4216-8b48-333ddb825de8",
"jti": "078047bc-fc1f-4c35-8abe-72834f7bcc44"
}

这是由 AuthGuard 装饰器保护的基本 protected 路由:

@Get('protected')
@UseGuards(AuthGuard('jwt'))
async protected(): Promise<string> {
return 'Hello Protected World';
}

我想添加选项并将该路由的访问限制为具有 manager_server 范围的人进入他们的 JWT。因此,在阅读了一些 AuthGuard 代码之后,我认为我可以编写如下代码:

@Get('protected')
@UseGuards(AuthGuard('jwt', {
scope: 'manage_server'
}))
async protected(): Promise<string> {
return 'Hello Protected World';
}

但是,我在文档中看不到可以使用此选项的地方。

我认为向 JWTStrategyvalidate 函数添加一个选项参数可以解决问题,但事实并非如此。这是我的 validate 函数(包含在 jwt.strategy.ts 文件中):

async validate(payload: JwtPayload, done: ((err: any, value: any) => void)) {
const user = await this.authService.validateUser(payload);
if (!user) {
return done(new UnauthorizedException(), false);
}
done(null, user);
}

非常感谢您的帮助,如果需要,请随时在评论中向我询问更多信息。

最佳答案

当您查看 code在 AuthGuard 中,options.callback 函数似乎是唯一可能的自定义。

我认为与其编写自己的支持范围检查的 AuthGuard,不如使用 ScopesGuard(或 RolesGuard)及其像 @Scopes('manage_server') 这样的装饰器。为此,您可以按照 docs 中的 RolesGuard 示例进行操作。 ,它也只是检查请求中 user 属性下的 JWT 负载的属性。


基本步骤

创建一个 @Scopes() 装饰器:

export const Scopes = (...scopes: string[]) => SetMetadata('scopes', scopes);

创建一个ScopesGuard:

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

canActivate(context: ExecutionContext): boolean {
const scopes = this.reflector.get<string[]>('scopes', context.getHandler());
if (!scopes) {
return true;
}
const request = context.switchToHttp().getRequest();
const user = request.user;
const hasScope = () => user.scopes.some((scope) => scopes.includes(scope));
return user && user.scopes && hasScope();
}
}

使用 ScopesGuard 作为所有路由的全局守卫(当没有给出范围时返回 true):

@Module({
providers: [
{
provide: APP_GUARD,
useClass: ScopesGuard,
},
],
})
export class ApplicationModule {}

然后在端点上使用它:

@Get('protected')
@UseGuards(AuthGuard('jwt'))
@Scopes('manage_server')
async protected(): Promise<string> {
return 'Hello Protected World';
}

关于javascript - NestJS:使用 JWT 向 AuthGuard 添加验证选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51932562/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com