如何在nestjs graphql中实现用户保护
Posted
技术标签:
【中文标题】如何在nestjs graphql中实现用户保护【英文标题】:how to implement user guards in nestjs graphql 【发布时间】:2020-08-10 04:47:31 【问题描述】:我正在尝试获取当前用户,但在解析器中我未定义,在 jwt 策略中我使用令牌获取用户 ibject 但在解析器中用户未定义
身份验证保护
import ExecutionContext, Injectable from '@nestjs/common';
import AuthGuard from '@nestjs/passport';
import GqlExecutionContext from '@nestjs/graphql';
import AuthenticationError from 'apollo-server-core';
import ExecutionContextHost from '@nestjs/core/helpers/execution-context-host';
@Injectable()
export class GqlAuthGuard extends AuthGuard('jwt')
canActivate(context: ExecutionContext)
const ctx = GqlExecutionContext.create(context);
const req = ctx.getContext();
return super.canActivate(
new ExecutionContextHost([req]),
);
handleRequest(err: any, user: any)
if (err || !user)
throw err || new AuthenticationError('GqlAuthGuard');
return user;
用户装饰器
import createParamDecorator from '@nestjs/common';
export const CurrentUser = createParamDecorator(
(data, req) => req.user )
;
应用模块
@Module(
imports: [
PassportModule.register( defaultStrategy: 'jwt' ),
JwtModule.register(
signOptions:
expiresIn: 3600,
,
),
SharedModule,
AuthModule,
GraphQLModule.forRoot(
autoSchemaFile: 'schema.gql',
context: ( req ) => ( req )
),
MongooseModule.forRoot(process.env.MONGO_URI,
useNewUrlParser: true ,
useUnifiedTopology: true
),
// RewardsModule,
OrdersModule,
],
controllers: [AppController],
providers: [AppService],
)
export class AppModule
解析器
import User from "src/types/user";
import GqlAuthGuard from "../guards/graphql.auth.guard";
@Resolver()
export class OrdersResolver
constructor(
private orderService: OrdersService
)
@Query(returns => [Order])
@UseGuards(GqlAuthGuard)
listOrders(@CurrentUser() user: User): Promise<Order>
console.log(user)
return this.orderService.listOrdersByUser(user.id);
我也尝试实施这里解释的解决方案NestJS Get current user in GraphQL resolver authenticated with JWT,但我仍然遇到同样的错误
【问题讨论】:
快速提问:您的 Nest 版本是什么?在 v6 和 v7 之间,createParamDecorator
函数发生了变化。
这些是nestjs版本 "@nestjs/common": "^7.0.0", "@nestjs/core": "^7.0.0", "@nestjs/graphql": "^ 7.3.4”、“@nestjs/jwt”:“^7.0.0”、“@nestjs/mongoose”:“^6.4.0”、“@nestjs/passport”:“^7.0.0”、“@nestjs /platform-express": "^7.0.0", "@nestjs/swagger": "^4.5.1",
【参考方案1】:
在 Nest v7 中,createParamDecorator
函数得到了更新。现在,而不是使用
export const CurrentUser = createParamDecorator(
(data, req) => req.user )
;
你应该改用这样的东西:
export const User = createParamDecorator(
(data: unknown, ctx: ExecutionContext) =>
const gqlCtx = GqlExecutionContext.create(ctx);
const request = gqlCtx.getContext().req;
return request.user;
,
);
为此,您还需要
context: (req) => (req)
在您的 GraphqlModule
配置中。
【讨论】:
【参考方案2】:这是完整的代码:
@Injectable()
export class RolesGuard_ implements CanActivate
constructor(private reflector: Reflector)
canActivate(context: ExecutionContext): boolean
const ctx = GqlExecutionContext.create(context);
const requiredRoles = this.reflector.getAllAndOverride<Role[]>(ROLES_KEY, [
context.getHandler(),
context.getClass(),
]);
if (!requiredRoles)
return true;
const user = ctx.getContext().req;
return requiredRoles.some((role) => user.role?.includes(role));
【讨论】:
【参考方案3】:这是我根据文档用于GraphqlJwtAuthGuard
的内容:
@Injectable()
export class GqlJwtAuthGuard extends AuthGuard('jwt')
constructor(private reflector: Reflector)
super();
canActivate(ctx: ExecutionContext)
const context = GqlExecutionContext.create(ctx);
const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
context.getHandler(),
context.getClass(),
]);
if (isPublic)
return true;
const req = context.getContext();
return super.canActivate(new ExecutionContextHost([req])); // NOTE
【讨论】:
以上是关于如何在nestjs graphql中实现用户保护的主要内容,如果未能解决你的问题,请参考以下文章