Для чего нужны guards в NestJS?

«Для чего нужны guards в NestJS?» — вопрос из категории NestJS, который задают на 26% собеседований Node.js Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Guards в NestJS — это механизм для авторизации и контроля доступа к маршрутам (эндпоинтам). Они выполняются до вызова обработчика запроса (controller method) и решают, следует ли разрешить выполнение запроса, основываясь на заданных условиях (например, наличие валидного JWT, проверка ролей пользователя).

Основная цель: Вынести логику проверки прав доступа из контроллеров в отдельные, переиспользуемые классы, соблюдая принцип единой ответственности (Single Responsibility Principle).

Пример реализации простого Guard для проверки аутентификации:

// auth.guard.ts
import { Injectable, CanActivate, ExecutionContext, UnauthorizedException } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private jwtService: JwtService) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const request = context.switchToHttp().getRequest();
    const token = this.extractTokenFromHeader(request);

    if (!token) {
      throw new UnauthorizedException('Токен отсутствует');
    }

    try {
      const payload = await this.jwtService.verifyAsync(token);
      // Присваиваем payload запросу, чтобы использовать в контроллере
      request['user'] = payload;
    } catch {
      throw new UnauthorizedException('Невалидный токен');
    }
    return true; // Запрос разрешен
  }

  private extractTokenFromHeader(request: Request): string | undefined {
    const [type, token] = request.headers['authorization']?.split(' ') ?? [];
    return type === 'Bearer' ? token : undefined;
  }
}

Применение Guard: Его можно применить на уровне контроллера, метода или глобально.

// cats.controller.ts
import { Controller, Get, UseGuards } from '@nestjs/common';
import { AuthGuard } from './auth.guard';

@Controller('cats')
@UseGuards(AuthGuard) // Весь контроллер защищен
// или @UseGuards(AuthGuard, RolesGuard) - несколько guards

export class CatsController {
  @Get('profile')
  getProfile(@Request() req) {
    // req.user доступен благодаря Guard
    return req.user;
  }
}

Ключевые преимущества использования Guards:

  • Чистота кода: Логика авторизации изолирована от бизнес-логики.
  • Переиспользование: Один Guard можно применить к множеству маршрутов.
  • Гибкость: Guards могут быть асинхронными, инжектировать сервисы (как JwtService в примере) и комбинироваться.
  • Интеграция с Exceptions: Легко интегрируются со встроенной системой исключений NestJS для возврата стандартизированных HTTP-ошибок (401, 403).