Ответ
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).
Ответ 18+ 🔞
А, Guards в NestJS! Ну это ж классика, ёпта. Представь себе такую ситуацию: у тебя есть бар, а на входе стоит здоровенный вышибала — вот это и есть Guard, только для твоих API-роутов. Его задача проста, как три копейки: проверить, можно ли пускать этого чувака внутрь, или послать его нахуй с невнятным криком «401 Unauthorized».
Зачем это, блядь, нужно? Ну смотри, без гвардов твоя бизнес-логика в контроллерах превращается в пиздопроебибну. Ты в каждом методе начинаешь с одного и того же: «а есть ли токен?», «а тот ли это пользователь?», «а не пидарас ли шерстяной?». Это же пиздец как неудобно! Гварды выносят всю эту муть в отдельный класс, чтобы твой контроллер занимался своим делом — отдавал котиков или что ты там делаешь — а не городил проверки.
Вот тебе простейший пример, как этот вышибала может выглядеть:
// 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);
// Кладём инфу о юзере в запрос, чтобы внутри контроллера к ней можно было доебаться
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;
}
}
А вот как этого стража натравить на свои эндпоинты:
// cats.controller.ts
import { Controller, Get, UseGuards } from '@nestjs/common';
import { AuthGuard } from './auth.guard';
@Controller('cats')
@UseGuards(AuthGuard) // Весь контроллер теперь под охраной. Хуй с горы не пролезет.
// Можно и несколько гвардов повесить, например, @UseGuards(AuthGuard, RolesGuard)
export class CatsController {
@Get('profile')
getProfile(@Request() req) {
// req.user уже лежит тут, спасибо нашему гварду
return req.user;
}
}
Так в чём же, блядь, магия и охуенность?
- Красота и порядок: В контроллере — чистая бизнес-логика, без всякого спагетти из проверок. Э бошка думай только о деле.
- Переиспользование на овердохуища: Написал один раз — используй на тысяче роутов. Не надо копипастить одно и то же.
- Мощь и гибкость: Они могут быть асинхронными, могут внедрять любые сервисы (как
JwtServiceвыше) и отлично дружат с системой исключений Nest. Хочешь — кинь 403, хочешь — 401. - Доверия ебать ноль: Они выполняются до того, как запрос доберётся до твоего обработчика. Так что если что-то не так — запрос даже не начнёт выполняться, сэкономив тебе ресурсы.
Короче, если не используешь гварды — ты, прости, распиздяй. Это базовый кирпич для любой нормальной авторизации, без него как без штанов.