Jwt 策略后 ExecutionContext 中缺少用户
User missing in ExecutionContext after Jwt strategy
目前我已经实现了 jwt guard,它工作得很好,使用 Passport,jwt 正在验证颁发的令牌,我可以通过 @Request 通过 req.user 来查看用户,在实现基于角色的身份验证后出现问题作为已经工作的 jwt 守卫的插件。
我遵循了 nestjs.com 提供的指导,但没有帮助。
https://docs.nestjs.com/guards
基本角色配置:
roles.decorator.ts
import { SetMetadata } from '@nestjs/common';
export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
roles.guard.ts
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private readonly 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;
console.log(user);
const hasRole = () => user.roles.some((role) => roles.includes(role));
return user && user.roles && hasRole();
}
}
RolesGuard 通过以下方式注入 app.module.ts
内容:
providers: [{
provide: APP_GUARD,
useClass: RolesGuard,
}]
我的控制器header验证:
@UseGuards(AuthGuard('jwt'))
@Roles('admin')
@Get('admin')
async admin(@Request() req) {
return this.authService.me(req.user);
}
它应该检查用户是否提供了 Bearer 令牌并且它是活动的,jwt 也会将用户分配给请求用户,我可以使用 @Request() req
然后 req.user
检索它,但是当涉及到@Roles('admin')
,它 returns undefined
在 roles.guard.ts
在 "console.log(user)" 部分最后,不允许用户看到给定的资源,似乎 RoleGuard
在 AuthGuard('jwt')
之前被注入,但是请求内部有 Brearer 令牌,所以它应该被转换给用户。
我正在考虑更改我的 jwt 策略并在那里实现 CanActivate 接口并将其写入那里,但这对我来说听起来不是一个好的解决方案,因为我想将它们分开。
我可以为您确认 RoleGuard
在 AuthGuard
之前被调用,因为 RoleGuard
是全局范围内的应用程序(在您定义的位置)和AuthGuard
是函数的局部范围。如果您不介意 RoleGuard
没有全局作用域而是针对每个方法作用域,即使需要编写更多代码,您也可以将其添加到 @UseGuards
装饰器。除此之外,就像你说的,你可以将两个守卫合二为一,但这可能会变得混乱和笨重。
目前我已经实现了 jwt guard,它工作得很好,使用 Passport,jwt 正在验证颁发的令牌,我可以通过 @Request 通过 req.user 来查看用户,在实现基于角色的身份验证后出现问题作为已经工作的 jwt 守卫的插件。
我遵循了 nestjs.com 提供的指导,但没有帮助。 https://docs.nestjs.com/guards
基本角色配置:
roles.decorator.ts
import { SetMetadata } from '@nestjs/common';
export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
roles.guard.ts
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private readonly 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;
console.log(user);
const hasRole = () => user.roles.some((role) => roles.includes(role));
return user && user.roles && hasRole();
}
}
RolesGuard 通过以下方式注入 app.module.ts
内容:
providers: [{
provide: APP_GUARD,
useClass: RolesGuard,
}]
我的控制器header验证:
@UseGuards(AuthGuard('jwt'))
@Roles('admin')
@Get('admin')
async admin(@Request() req) {
return this.authService.me(req.user);
}
它应该检查用户是否提供了 Bearer 令牌并且它是活动的,jwt 也会将用户分配给请求用户,我可以使用 @Request() req
然后 req.user
检索它,但是当涉及到@Roles('admin')
,它 returns undefined
在 roles.guard.ts
在 "console.log(user)" 部分最后,不允许用户看到给定的资源,似乎 RoleGuard
在 AuthGuard('jwt')
之前被注入,但是请求内部有 Brearer 令牌,所以它应该被转换给用户。
我正在考虑更改我的 jwt 策略并在那里实现 CanActivate 接口并将其写入那里,但这对我来说听起来不是一个好的解决方案,因为我想将它们分开。
我可以为您确认 RoleGuard
在 AuthGuard
之前被调用,因为 RoleGuard
是全局范围内的应用程序(在您定义的位置)和AuthGuard
是函数的局部范围。如果您不介意 RoleGuard
没有全局作用域而是针对每个方法作用域,即使需要编写更多代码,您也可以将其添加到 @UseGuards
装饰器。除此之外,就像你说的,你可以将两个守卫合二为一,但这可能会变得混乱和笨重。