我正在尝试使用passwordJS保护我的GraphQL端点,以便对该端点的每个调用都使用AuthGuard来验证令牌并根据request.user设置用户,就像在使用以下代码的控制器中所做的那样:
@Get('findAll')
@UseGuards(AuthGuard('jwt'))
findAll(@Req() request): Promise<Array<Thing>> {
return this.thingService.findByUser(request.user.email);
}
我想在graphQL端点中使用它,它是这样创建的:
consumer
.apply(graphiqlExpress({ endpointURL: '/graphql' }))
.forRoutes('/graphiql')
.apply(
graphqlExpress(req => ({ schema, rootValue: req })),
¿?,
)
.forRoutes('/graphql');
我想我可以像在graphqlExpress函数之后一样将其设置为中间件函数,但是我没有成功。有什么想法吗?
提前谢谢!
修改
作为一种解决方法,我已经实现了Nest Docs上提出的解决方案,该解决方案在每个必须保护的查询/突变中都使用@UseGuard。
但是,我想保护整个端点,这样就不会为每个受保护的解析程序调用防护,而是在主请求上仅调用一次。这有可能吗?
答案 0 :(得分:1)
从技术上讲这是可能的,但是写起来是很草率的,而且绝对不能保证它可以与Fastify一起使用,所以请注意。功能的实质来自于您实现中间件的模块。我最后用AppModule
(我不建议这样做(至少不是全部代码的全部))进行了所有操作,但是仍然有效。
您需要使防护罩为custom provider,以便可以将其插入任何上下文中。
然后,您需要使用ExecutionContext
模拟req, res, next
。如果您想要输入安全性,这说起来容易做起来难,但是如果您不关心这个(我不是这样做的话),那么请给as any
打个电话,然后每天称呼它。
此后,在中间件使用者中,运行apply
并将this.guard.canActivate
与创建的模拟ExecutionContext
一起使用。将此中间件async
和await
进行canActivate
调用。检查它是否返回为true
,如果不是,则返回throw new <ErrorOfYourChoice>()
并动臂。设置好了。代码看起来(大概)是这样的:
import {
BadRequestException,
CanActivate,
Inject,
MiddlewareConsumer,
Module,
NestModule,
} from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { AppResolver } from './app.resolver';
import { GraphQLModule } from '@nestjs/graphql';
import { JwtModule } from '@nestjs/jwt';
import { AuthGuard, PassportModule } from '@nestjs/passport';
import { JwtStrategy } from './jwt.strategy';
@Module({
imports: [
GraphQLModule.forRoot({
autoSchemaFile: true,
}),
JwtModule.register({ secret: 'secret' }),
PassportModule.register({ defaultStrategy: 'jwt' }),
],
controllers: [AppController],
providers: [
AppService,
AppResolver,
JwtStrategy,
{ provide: 'CustomGuard', useClass: AuthGuard() },
],
})
export class AppModule implements NestModule {
constructor(@Inject('CustomGuard') private readonly guard: CanActivate) {}
configure(consumer: MiddlewareConsumer) {
consumer
.apply(async (req, res, next) => {
const canActivate = await this.guard.canActivate({
switchToHttp: () => ({
getRequest: () => req,
getResponse: () => res,
getNext: () => next,
}),
} as any);
if (canActivate) {
next();
} else {
throw new BadRequestException();
}
})
.forRoutes('graphql');
}
}
您可以检查this repository是否已连接并正常工作。使用POST /login -d 'username=test1&password=changeme'
登录,获取JWT并随意使用它。
答案 1 :(得分:-1)
但是,我想保护整个端点,这样就不会为每个受保护的解析器调用保护,而只在主请求上调用一次。这甚至可能吗?
通过在此处使用来自 NestJS 的参考全局方法,我能够获得一个中间件函数来解析每个查询/突变:https://docs.nestjs.com/graphql/field-middleware#global-field-middleware。