node.js - NestJS 获取使用 JWT 身份验证的 GraphQL 解析器中的当前用户
问题描述
我目前正在将带有 Passport.js 的 JWT 身份验证实现到 NestJS 应用程序中。
在我的一些 GraphQL 解析器中,我需要访问当前经过身份验证的用户。我知道护照会将经过身份验证的用户附加到请求对象(至少我希望这是正确的),但我不知道如何在解析器中访问请求对象。
我关注了问题https://github.com/nestjs/nest/issues/1326和提到的链接https://github.com/ForetagInc/fullstack-boilerplate/tree/master/apps/api/src/app/auth问题里面。我在 GraphQL 解析器方法中看到了一些@Res() res: Request
用作方法参数的代码,但我总是undefined
得到res
.
这些是我目前的实现:
GQL 认证
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 守卫也适用于不需要访问用户的方法。但是对于需要访问当前经过身份验证的用户的方法,我看不出有什么办法。
有没有办法完成这样的事情?
解决方案
终于找到了答案... 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
推荐阅读
- php - 查看 [layouts.account] 未找到。什么问题?[AsgardCms]
- if-statement - 带有嵌套If语句的Google表格多个条件?
- python-3.x - 从一个点到一组有限点的距离
- ios - 编译 IPA 时 Firebase Analytics 不起作用
- amazon-cloudfront - CloudFront 修改 JS/CSS 内容
- angular - 如何在离子中验证表单
- ios - 上下文菜单选择颜色和框架大小 Swift 5 iOS 13
- python - Python - 如何通过 socket.makefile 执行套接字通信?
- spring - @RefreshScope 不适用于外部配置文件
- domain-driven-design - 层次系统中的聚合根与聚合