NestJS:如何在从 JWT AuthGuard 扩展的 GraphQL 自定义 Guard 中从请求中获取用户
Posted
技术标签:
【中文标题】NestJS:如何在从 JWT AuthGuard 扩展的 GraphQL 自定义 Guard 中从请求中获取用户【英文标题】:NestJS: How to get User from the request in a GraphQL custom Guard which extends from JWT AuthGuard 【发布时间】:2020-03-26 00:01:10 【问题描述】:我使用 Passport 和 GraphQL,如果我使用自己的自定义保护来获取用户的角色,它就不起作用。我无法通过 Guard 中的请求访问用户,这是故意的吗?我认为它应该是请求的一部分(我对 NestJS 完全陌生),为什么我不能得到它?我想直接从用户对象中获取用户的角色,并且只允许具有 Admin 的用户访问特定路由,例如完整的用户列表。
这是我的 GraphQL 守卫,控制台日志总是返回 undefined
@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()
获取用户,但我无法在警卫内获取用户对象。我正在尝试从请求中获取用户,但这是否可能在 Guard 中?我尝试了很多东西,我不知道该怎么做了。
我还尝试使用不同的代码执行另一个角色保护,我再次尝试从请求中获取用户,但我无法从请求中获取用户。
@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();
【问题讨论】:
【参考方案1】:在您的GraphqlPassportAuthGuard.canActivate()
上,您应该调用super.canActivate(context)
,这是@nestjs/passport AuthGuard
将用户放入请求对象的位置。
如果由于某种原因,您不希望在用户未通过身份验证时抛出守卫,您还必须覆盖 AuthGuard.handleRequest(err, user, info, context)
【讨论】:
抱歉耽搁了,我刚试过这个,我仍然有相同的结果undefined
,我应该在super.canActivate
之后仍然调用相同的2行吗?第二行ctx.getContext().req
仍然没有我正在寻找的用户。您介意提供canActive
方法的完整代码吗?我是要删除某些东西还是调用其他东西?我对 NestJS 完全陌生,我有点困惑。我的主要目标是获取用户的角色并在用户没有必要角色时阻止他
你应该 await
获取 super.canActivate 因为它返回一个 Promise,抱歉我没有在我的原始答案中提到。所以定义canActivate
async
并调用await super.canActivate(context)
。还要记住将返回类型更改为Promise<boolean>
以上是关于NestJS:如何在从 JWT AuthGuard 扩展的 GraphQL 自定义 Guard 中从请求中获取用户的主要内容,如果未能解决你的问题,请参考以下文章
PassportJS、NestJS:AuthGuard('jwt') 的 canActivate 方法
NestJS:使用 JWT 向 AuthGuard 添加验证选项
我在我的 nestJS 应用程序(使用 authGuard)中使用了 passport-jwt 身份验证策略,如何访问我的控制器中的令牌有效负载?
在没有 AuthGuard 的路由上获取 nestjs 中的当前用户