当前位置: 首页 > 知识库问答 >
问题:

NestJS获取GraphQL解析器中的当前用户,通过JWT验证

孟福
2023-03-14

我目前正在实现JWT身份验证,Passport.js到NestJS应用程序中。

在我的一些GraphQL解析器中,我需要访问当前已认证的用户。我知道passport会将经过身份验证的用户附加到请求对象上(至少我希望这是正确的),但是我不知道如何在解析器中访问请求对象。

我关注了问题https://github.com/nestjs/nest/issues/1326和问题中提到的链接https://github . com/foreaginc/full stack-boilerplate/tree/master/apps/API/src/app/auth。我看到一些代码在GraphQL解析器方法中使用< code>@Res() res: Request作为方法参数,但是我总是得到< code>res的< code>undefined。

这些是我当前拥有的实现:

GQLATH

import { Injectable, ExecutionContext } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { GqlExecutionContext } from '@nestjs/graphql';
import { ExecutionContextHost } from '@nestjs/core/helpers/execution-context-host';
import { AuthenticationError } from 'apollo-server-core';

@Injectable()
export class GqlAuthGuard extends AuthGuard('jwt') {
  canActivate(context: ExecutionContext) {
    const ctx = GqlExecutionContext.create(context);
    const { req } = ctx.getContext();
    console.log(req);

    return super.canActivate(new ExecutionContextHost([req]));
  }

  handleRequest(err: any, user: any) {
    if (err || !user) {
      throw err || new AuthenticationError('GqlAuthGuard');
    }
    return user;
  }
}

需要访问当前用户的解析器

import { UseGuards, Req } from '@nestjs/common';
import { Resolver, Query, Args, Mutation, Context } from '@nestjs/graphql';
import { Request } from 'express';

import { UserService } from './user.service';
import { User } from './models/user.entity';
import { GqlAuthGuard } from '../auth/guards/gql-auth.guard';

@Resolver(of => User)
export class UserResolver {
  constructor(private userService: UserService) {}

  @Query(returns => User)
  @UseGuards(GqlAuthGuard)
  whoami(@Req() req: Request) {
    console.log(req);
    return this.userService.findByUsername('aw');
  }
}

智威汤逊战略

import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { AuthService } from './auth.service';
import { JwtPayload } from './interfaces/jwt-payload.interface';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(private readonly authService: AuthService) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: process.env.SECRET,
    });
  }

  async validate(payload: JwtPayload) {
    const user = await this.authService.validateUser(payload);
    if (!user) {
      throw new UnauthorizedException();
    }
    return user;
  }
}

授权和创建JWT令牌可以正常工作。GraphQL保护对于不需要访问用户的方法也可以正常工作。但是对于需要访问当前经过身份验证的用户的方法,我看不到获得它的方法。

有办法完成这样的事情吗?

共有3个答案

景元徽
2023-03-14

另一种方法是使用您正在使用的任何包验证web令牌,然后创建decorator<code>get user.decorators.ts

import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';


export const GetUser = createParamDecorator((data, context: ExecutionContext)  => {
 const ctx = GqlExecutionContext.create(context).getContext();
return ctx.user
});

然后在您的解析器中,您可以使用此装饰器(@GetUser()user: User)访问用户

谭刚毅
2023-03-14

为了将AuthGuard与GraphQL一起使用,扩展内置的AuthGuard类并覆盖getRequest()方法。创建一个名为gql.guard.ts的文件(命名您的愿望)

@Injectable()
export class GqlAuthGuard extends AuthGuard('jwt') {
  getRequest(context: ExecutionContext) {
    const ctx = GqlExecutionContext.create(context);
    return ctx.getContext().req;
  }
}

要在图形解析器中获取当前经过身份验证的用户,您可以定义一个@MONtUser()装饰器(创建一个名为user.decorator.graphql.ts的文件)

import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';

export const CurrentUser = createParamDecorator(
  (data: unknown, context: ExecutionContext) => {
    const ctx = GqlExecutionContext.create(context);
    return ctx.getContext().req.user;
  },
);

要在解析器中使用上面的修饰符,请确保将其作为查询或变异的参数

@Query(returns => User)
@UseGuards(GqlAuthGuard)
whoAmI(@CurrentUser() user: User) {
  return this.usersService.findById(user.id);
}

阅读更多:https://docs.nestjs.com/security/authentication#graphql

姚善
2023-03-14

终于找到了答案。。。https://github.com/nestjs/graphql/issues/48#issuecomment-420693225为我指出了创建用户装饰器的正确方向

// user.decorator.ts
import { createParamDecorator } from '@nestjs/common';

export const CurrentUser = createParamDecorator(
  (data, req) => req.user,
);

然后在我的解析器方法中使用它:

 import { User as CurrentUser } from './user.decorator';

 @Query(returns => User)
  @UseGuards(GqlAuthGuard)
  whoami(@CurrentUser() user: User) {
    console.log(user);
    return this.userService.findByUsername(user.username);
  }

现在一切都按预期进行。所以这个答案的所有学分都归https://github.com/cschroeter

 类似资料:
  • 我有一个Spring Boot REST应用程序,它使用JWT令牌进行授权。我想使用AuthenticationPrincipal注释获取控制器中当前登录的用户。但如果我从loadUserByUsername返回自定义模型,并且auth停止工作,它总是返回null。我的模型实现了用户详细信息。 我试图扩展组织。springframework。安全果心用户详细信息。但我从JWTAuthenticat

  • 我有一个正在解析的用户列表。通用域名格式 我需要检索其中一些用户,我有所有必要的ID。例如,parse中存储了50个用户,但我只需要10个。 有了这10个ID,我需要获得用户。 我是邮递员,我做下一件事: 我得到了正确的数据。 如何将其转换为改装呼叫?如何在改装中使用“where”语句? 感谢所有。

  • 我试图通过构建一个具有以下模式的服务器来熟悉Graphql: 并映射到以下数据: 在编写解析器时,我注意到很多样板代码——我必须为每个持有外键的对象成员编写概念上相同的字段解析器。 有没有办法通过ID创建类型解析器?例如,字段或查询总是由

  • 我已经建立了一个keycloak服务器,我正在开发一个API,这将在互联网上。API将接收第三方(客户端)的调用。这些客户机将首先使用clientId和secret调用keycloak服务器以获取令牌,然后使用此令牌调用我的API。 null 我现在看到的是一个示例,它设置了一个JWTAuthHandler 来自我的API(用于JWTAuth)的调用的Keycloak配置是: 当我在postman

  • 您好,我正在使用平均堆栈和jwt登录,我想限制一些数据只有userRole'admin'这是我的user.js 这就是我验证jwt令牌的方法 这是我希望使用verifyToken函数仅为'admin'角色限制的数据 我的问题是,我如何访问当前登录的用户信息,并仅使管理员可读的/特殊的

  • 我有一个Web角前端,API网关受Cognito和Lambda保护,用于其他业务用例。登录和授权工作正常。我正在使用AWS Javascript SDK进行授权。像https://s3.amazonaws.com/solutions-reference/mobile-backend/latest/mobile-app-backend.pdf 在我的lambda中,我需要获得其他用户的信息,如名字、