Menu
CoddyTech

Guards

Часть раздела TypeScript и NestJS путешествия по Node.js на Coddy. Урок 18 из 24.

Любой может создавать или удалять задачи. Страж решает, может ли запрос дойти до обработчика: Nest вызывает его canActivate, и если метод возвращает false, Nest отвечает кодом 403 «Доступ запрещён», не запуская метод.

@Injectable()
export class OpenHoursGuard implements CanActivate {
    canActivate(context: ExecutionContext): boolean {
        const hour = new Date().getHours();
        return hour >= 9 && hour < 17;
    }
}

@Post()
@UseGuards(OpenHoursGuard)
book() {}

context.switchToHttp().getRequest() возвращает запрос; Node хранит имена его заголовков в нижнем регистре, поэтому читайте request.headers['x-api-key']. @UseGuards, указанный для метода, защищает этот метод. Указанный для класса контроллера, он защищает все методы этого класса.

challenge icon

Задание

Легко

Сейчас любой может создавать и удалять задачи. Защитите два маршрута, изменяющих данные, с помощью API-ключа: секрета, который клиент отправляет в заголовке запроса. Чтение остается доступным всем.

  1. Откройте src/common/api-key.guard.ts. В методе canActivate класса ApiKeyGuard прочитайте заголовок x-api-key запроса. context.switchToHttp().getRequest() возвращает запрос, а имена его заголовков всегда записываются строчными буквами.
  2. Возвращайте true только если этот заголовок равен process.env.API_KEY, значение которого в этом уроке — tasks-key-123. Во всех остальных случаях возвращайте false, в том числе если заголовок отсутствует. Когда guard возвращает false, Nest отвечает кодом 403 и не запускает метод маршрута.
  3. В src/tasks/tasks.controller.ts импортируйте ApiKeyGuard из ../common/api-key.guard, а UseGuards — из @nestjs/common. Добавьте @UseGuards(ApiKeyGuard) к методу create (POST /tasks) и методу remove (DELETE /tasks/:id). Не добавляйте его к классу: тогда будут заблокированы и маршруты GET.
  4. GET /tasks, GET /tasks/:id и GET /stats продолжат работать без ключа.

Попробуйте: отправьте POST-запрос с { "title": "Buy milk" } на /tasks без заголовка. Вы получите 403:

{ "message": "Forbidden resource", "error": "Forbidden", "statusCode": 403 }

Откройте поле Headers на панели запроса, добавьте строку x-api-key: tasks-key-123 и отправьте POST-запрос еще раз: получите 201 и новую задачу. С x-api-key: guess вы получите 403. Для DELETE /tasks/4 ключ тоже необходим: без него — 403, с ним — 204. GET /tasks работает вообще без заголовка.

Попробуйте сами

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';

@Injectable()
export class ApiKeyGuard implements CanActivate {
    canActivate(context: ExecutionContext): boolean {
        // Пропускайте запрос, только если его заголовок x-api-key
        // совпадает с process.env.API_KEY.
        return true;
    }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела TypeScript и NestJS

Потренируйтесь самостоятельно: Песочница Express