我有KeysModule,可用于添加或删除API密钥。我需要这些密钥来保护某些路由免遭未经授权的访问。 为了保护这些路线,我创建了ApiGuard:
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
@Injectable()
export class ApiGuard implements CanActivate {
async canActivate(
context: ExecutionContext,
): Promise<boolean> {
const request = context.switchToHttp().getRequest();
return request.headers.api_key;
}
}
然后在路线中使用它:
@Get('/protected')
@UseGuards(ApiGuard)
async protected(@Headers() headers: Api) {
const key = await this.ks.findKey({ key: headers.api_key });
if (!key || !key.active) return 'Invalid Key';
return 'Your API key works';
}
其中ks是KeyService,用于检查密钥是否正确。 此解决方案有效,但很愚蠢。我必须在要使用此防护的任何地方复制并粘贴一些代码行(我的意思是路由中的行)。
我试图将所有逻辑移至ApiGuard,但出现错误,无法将KeyService注入ApiGuard类。解释一下,我在KeysModule的提供程序中有KeyService,但是ApiGuard在全球范围内使用。
你知道怎么做吗?
答案 0 :(得分:0)
您可以像在带有Injectable
注释的任何对象中一样,在防护中注入服务。
如果您的ApiGuard需要KeyService,则有两种选择:
答案 1 :(得分:0)
也许为时已晚,但我遇到了同样的问题并找到了解决方案。也许有更好的选择了,但是对我来说工作正常:
将KeysModule定义为全局模块,您可以在nestjs文档中检查操作方法:https://docs.nestjs.com/modules
执行此操作后:
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
@Injectable()
export class ApiGuard implements CanActivate {
constructor(
@Inject('KeyService')
private readonly ks
) {}
const key = await this.ks.findKey();
"YOUR_CODE_HERE..."
}
希望对您或将来会遇到此问题的人有所帮助。
答案 2 :(得分:0)
要在后卫中注入服务。您可以创建一个全局模块。
// ApiModule
import {Module,Global} from '@nestjs/common';
import {KeyService} from '../';
@Global()
@Module({
providers: [ KeyService ],
exports: [KeyService]
})
export class ApiModule {}
然后像这样将服务注入警卫
// guard
export class ApiGuard implements CanActivate {
constructor(@Inject('KeyService') private readonly KeyService) {}
}
async canActivate(context: ExecutionContext) {
// your code
throw new ForbiddenException();
}
现在问题可以解决。但是我还有另一个问题。我想向服务中注入一些东西,但是出现了这个错误:
嵌套不能解析AuthGuard的依赖项(?,+)。请确保索引[0]的参数在当前上下文中可用。
这是我的解决方案:
要在KeyService中注入其他依赖性,例如nestjs docs。
从任何模块外部注册的全局警卫(如上例所示,使用useGlobalGuards())不能注入依赖项,因为这是在任何模块的上下文之外进行的。
这是他们的样品:
// app.module.js
import { Module } from '@nestjs/common';
import { APP_GUARD } from '@nestjs/core';
@Module({
providers: [
{
provide: APP_GUARD,
useClass: RolesGuard,
},
],
})
export class ApplicationModule {}
成功了,现在我可以使用全局防护了,而没有依赖错误。
答案 3 :(得分:0)
guard 中使用的服务必须在其模块中导出。提供服务还不够!