Внедрить службу в охрану в Nest.JS - PullRequest
0 голосов
/ 17 октября 2018

У меня есть 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.Чтобы объяснить, у меня есть KeyService в провайдерах в KeysModule, но ApiGuard используется во всем мире.

У вас есть идеи, как это сделать?

Ответы [ 3 ]

0 голосов
/ 04 марта 2019

Возможно, уже слишком поздно, но я запустил ту же проблему и нашел решение.Может быть, есть и лучший, но он работает для меня правильно:

Определите KeysModule как глобальный модуль, вы можете проверить, как это сделать, в nestjs docs: 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..."

}

Надеюсь, это поможет вам или кому-то, кто застрянет с этим в будущем.

0 голосов
/ 26 апреля 2019

Чтобы ввести службу в охрану. Вы можете создать глобальный модуль.

// 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();
  }

Теперь проблема может быть решена. Но яУ меня есть другая проблема. Я хочу внедрить что-то в сервис, но получил эту ошибку:

Nest не может разрешить зависимости 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 {}

Это сработало. Теперь я могу использовать guard global без ошибки зависимости.

0 голосов
/ 18 октября 2018

Вы можете внедрить службу в охрану, как в любом объекте, отмеченном Injectable.Если вашему ApiGuard требуется KeyService, у вас есть два варианта:

  • Добавить ApiGuard в модуль, который импортирует KeysModule.Затем импортируйте созданный модуль для использования ApiGuard глобально
  • Добавьте ApiGuard в KeysModule и экспортируйте его.
...