Menu
CoddyTech

Guard

CoddyのNode.jsジャーニー「TypeScriptとNestJS」セクションの一部。レッスン 18/24。

誰でもタスクを作成または削除できます。ガードは、リクエストがハンドラーに到達できるかどうかを判断します。NestはそのcanActivateを呼び出し、falseが返されると、メソッドを実行せずに403 Forbiddenを返します。

@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

チャレンジ

簡単

現在は誰でもタスクを作成または削除できます。データを変更する2つのルートをAPIキーで保護しましょう。APIキーとは、クライアントがリクエストヘッダーで送信する秘密の値です。読み取りは誰でも引き続き行えます。

  1. src/common/api-key.guard.tsを開きます。ApiKeyGuardのcanActivateメソッドで、リクエストのx-api-keyヘッダーを読み取ります。context.switchToHttp().getRequest()でリクエストを取得でき、ヘッダー名は常に小文字です。
  2. そのヘッダーがprocess.env.API_KEY(このレッスンではtasks-key-123に設定されています)と一致する場合に限り、trueを返します。ヘッダーがない場合も含め、それ以外の場合はすべてfalseを返します。ガードがfalseを返すと、Nestは403を返し、ルートのメソッドは実行されません。
  3. src/tasks/tasks.controller.tsで、../common/api-key.guardからApiKeyGuardを、@nestjs/commonからUseGuardsをインポートします。createメソッド(POST /tasks)とremoveメソッド(DELETE /tasks/:id)に@UseGuards(ApiKeyGuard)を付けます。クラスには付けないでください。そうするとGETルートも保護されてしまいます。
  4. GET /tasks、GET /tasks/:id、GET /statsは、キーなしで引き続き動作します。

試してみましょう: ヘッダーを付けずに{ "title": "Buy milk" }を/tasksにPOSTします。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プレイグラウンド