Menu
CoddyTech

Bộ bảo vệ

Thuộc phần TypeScript và NestJS trong hành trình Node.js của Coddy. Bài học 18 trên 24.

Bất kỳ ai cũng có thể tạo hoặc xóa tác vụ. Guard quyết định liệu một yêu cầu có thể đến trình xử lý hay không: Nest gọi canActivate, và khi phương thức này trả về false, Nest phản hồi 403 Forbidden mà không chạy phương thức.

@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() cung cấp yêu cầu; Node lưu tên header ở dạng chữ thường, vì vậy hãy đọc request.headers['x-api-key']. @UseGuards trên một phương thức sẽ bảo vệ phương thức đó. Trên lớp controller, nó bảo vệ mọi phương thức trong lớp.

challenge icon

Thử thách

Dễ

Hiện tại, bất kỳ ai cũng có thể tạo hoặc xóa tác vụ. Khóa hai tuyến thay đổi dữ liệu bằng API key: một bí mật mà máy khách gửi trong tiêu đề yêu cầu. Mọi người vẫn có thể đọc dữ liệu.

  1. Mở src/common/api-key.guard.ts. Trong phương thức canActivate của ApiKeyGuard, đọc tiêu đề x-api-key của yêu cầu. context.switchToHttp().getRequest() trả về yêu cầu, và tên tiêu đề luôn viết thường.
  2. Chỉ trả về true khi tiêu đề đó bằng process.env.API_KEY, giá trị mà bài học này đặt là tasks-key-123. Trong mọi trường hợp khác, kể cả khi thiếu tiêu đề, hãy trả về false. Khi guard trả về false, Nest phản hồi bằng mã 403 và không chạy phương thức của tuyến đó.
  3. Trong src/tasks/tasks.controller.ts, nhập ApiKeyGuard từ ../common/api-key.guard và UseGuards từ @nestjs/common. Đặt @UseGuards(ApiKeyGuard) trên phương thức create (POST /tasks) và phương thức remove (DELETE /tasks/:id). Đừng đặt nó trên lớp, vì như vậy các tuyến GET cũng bị khóa.
  4. GET /tasks, GET /tasks/:id và GET /stats vẫn hoạt động mà không cần key.

Thử nhé: Gửi POST { "title": "Buy milk" } đến /tasks mà không có tiêu đề. Bạn sẽ nhận được mã 403:

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

Mở trường Headers trên thanh yêu cầu, thêm dòng x-api-key: tasks-key-123, rồi gửi lại POST: bạn sẽ nhận được mã 201 cùng tác vụ mới. Với x-api-key: guess, bạn sẽ nhận được mã 403. DELETE /tasks/4 cũng cần key: mã 403 nếu thiếu key, mã 204 nếu có key. GET /tasks hoạt động mà không cần tiêu đề nào.

Tự làm thử

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

@Injectable()
export class ApiKeyGuard implements CanActivate {
    canActivate(context: ExecutionContext): boolean {
        // Chỉ cho phép yêu cầu đi qua khi header x-api-key của yêu cầu
        // trùng với process.env.API_KEY.
        return true;
    }
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong TypeScript và NestJS

Tự luyện tập: Playground Express