Typescript NestJS:如何在从JWT AuthGuard扩展而来的GraphQL自定义保护中从请求获取用户

Typescript NestJS:如何在从JWT AuthGuard扩展而来的GraphQL自定义保护中从请求获取用户,typescript,graphql,nestjs,Typescript,Graphql,Nestjs,我使用Passport和GraphQL,如果我使用自己的自定义保护来获取用户的角色,那么它就是不起作用。我无法通过警卫中的请求访问用户,这是故意的吗?我认为这应该是请求的一部分(我对NestJS完全陌生),所以为什么我不能得到它呢?我想直接从用户对象获取用户角色,并且只允许使用Admin的用户访问特定的路由,比如完整的用户列表 这是我的GraphQL guard,控制台日志总是返回未定义 @Injectable() export class GraphqlPassportAuthGuard ex

我使用Passport和GraphQL,如果我使用自己的自定义保护来获取用户的角色,那么它就是不起作用。我无法通过警卫中的请求访问用户,这是故意的吗?我认为这应该是请求的一部分(我对NestJS完全陌生),所以为什么我不能得到它呢?我想直接从用户对象获取用户角色,并且只允许使用Admin的用户访问特定的路由,比如完整的用户列表

这是我的GraphQL guard,控制台日志总是返回未定义

@Injectable()
export class GraphqlPassportAuthGuard extends AuthGuard('jwt') {
  roles: string[];

  constructor(roles?: string | string[]) {
    super();
    this.roles = Array.isArray(roles) ? roles : [roles];
  }

  canActivate(context: ExecutionContext): boolean {
    const ctx = GqlExecutionContext.create(context);
    const req = ctx.getContext().req;
    console.log('graphql guard user', req && req.user)
    return true;
  }

  getRequest(context: ExecutionContext) {
    const ctx = GqlExecutionContext.create(context);
    const req = ctx.getContext().req;
    console.log('graphql guard user', req && req.user)
    return req;
  }
}
我尝试将其与以下代码一起使用

export const CurrentUser = createParamDecorator(
  (data, [root, args, ctx, info]) => {
    return ctx.req.user;
  },
);

@Resolver()
export class UsersResolver {
  constructor() { } 

  @Query(() => UserDto)
  @UseGuards(GraphqlPassportAuthGuard)
  whoAmI(@CurrentUser() user: User) {
    return user;
  }
}
app.module.ts

@Module({
  imports: [
    GraphQLModule.forRoot({
      autoSchemaFile: 'schema.gql',
      context: ({ req }) => ({ req }),
    }),
    // ...
});
我可以使用自定义装饰器从
@CurrentUser()
获取用户,但无法在防护内部获取用户对象。我正在尝试从请求中获取用户,但这是否可能在警卫中实现?我尝试了很多事情,我不知道该怎么办了

我还尝试使用不同的代码执行另一个角色,我再次尝试从请求中获取用户,但无法从请求中获取用户

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

  canActivate(context: ExecutionContext): boolean {
    const handler = context.getHandler();
    const http = context.switchToHttp();
    const request = context.switchToHttp().getRequest();
    const roles = this.reflector.get<string[]>('roles', context.getHandler());
    console.log('rolesGuard', roles, request && request.user)
    if (!roles || !request || !request.user) {
      return true;
    }
    const user = request && request.user;
    const hasRole = () =>
      user.roles.some(role => !!roles.find(item => item === role));

    return user && user.roles && hasRole();
  }
}
@Injectable()
导出类RolesGuard实现CanActivate{
构造函数(专用只读反射器:反射器){}
canActivate(上下文:ExecutionContext):布尔值{
const handler=context.getHandler();
const http=context.switchToHttp();
const request=context.switchToHttp().getRequest();
const roles=this.reflector.get('roles',context.getHandler());
console.log('rolesGuard',roles,request&&request.user)
if(!roles | | |!request | |!request.user){
返回true;
}
const user=request&&request.user;
常量hasRole=()=>
user.roles.some(role=>!!roles.find(item=>item==role));
返回user&&user.roles&&hasRole();
}
}

图形上,您应该调用
super.canActivate(context)
,这就是@nestjs/passport
AuthGuard
将用户放入请求对象的地方


如果出于某种原因,您不希望在用户未经身份验证时防护程序抛出,那么您还必须覆盖
AuthGuard.handleRequest(err,user,info,context)

很抱歉延迟,我刚刚尝试了此操作,但仍有相同的结果
未定义,我应该在
super.canActivate
之后仍然调用相同的2行吗?第二行
ctx.getContext().req
仍然没有我要查找的用户。您介意提供
canActive
方法的完整代码吗?我应该删除某个内容还是调用其他内容?我是NestJS的新手,有点困惑。我的主要目标是获取用户的角色,如果用户没有必要的角色,则阻止他。您应该
等待super.canActivate的
启动,因为它返回一个承诺,很抱歉,我在最初的回答中没有提到。因此,请定义
canActivate
async
并调用
wait super.canActivate(context)
。还记得将返回类型更改为
Promise
Awesome,非常感谢,我已经找了很久了:)