APIの保護 - クイックスタートガイド
なぜそれが必要なのでしょうか?
CrowdHandlerは、保護されたウェブページやアプリケーション画面にアクセスを試みるエンドユーザーを「待機室」にリダイレクトすることで機能します。フロントエンドの動作を制御するAPIエンドポイントが特定可能な場合(例えば、クライアントサイドから呼び出されている場合など)、技術に精通したユーザー、転売業者、および/またはボットは、APIエンドポイントを通じて直接目的の情報を取得しようと、フロントエンドを完全に迂回しようとする可能性があります。
心配したほうがいいでしょうか?
決定的な根拠とは言えませんが、以下の基準のうち1つ以上が当てはまる場合は、APIエンドポイントを保護することを検討すべきです:
- トランザクション用APIのエンドポイントは検出可能です。
- 貴社は、需要が供給を上回る可能性が高い人気商品を販売しています。
- 御社のユーザー層はテクノロジーに精通しています。
- 御社の製品は、転売業者に狙われやすいことで知られています。
行動を起こす
シナリオ 1 - API エンドポイントは 同じ 保護対象のサイトとしてドメインを指定します。
例
保護対象ドメイン-https://tickets.example.com
APIエンドポイント-https://tickets.example.com/v1/api
前提条件
すでに、当社のCDNまたはサーバーサイド統合オプションのいずれかを使用して、サイトをCrowdHandlerと連携させているはずです。
CrowdHandler のルーム保護オプション
すべてのURL
これ以上の対応は不要です
正規表現に一致するURL
- エンドユーザーが需要の高い商品をカートに追加するページは、保護する必要があります。
- 需要の高い商品をカートに追加するためのAPIルートは、保護する必要があります。

考慮事項
私のAPIのURLルーティングは汎用的なものです
APIのURLルートに変更を加え、製品IDまたはスラッグをクエリ文字列パラメータとして含めるようにしてください。
https://tickets.example.com/v1/api/basket→https://tickets.example.com/v1/api/basket?id=64398
これにより、CrowdHandlerでのルームマッチが行われます。
なりすましを防止する
API では、API URL に含まれる商品 ID またはスラグが、ペイロード内の商品 ID またはスラグと一致することを確認してください。この追加の保護措置を講じないと、クエリ文字列内の商品 ID またはスラグが改ざんされ、CrowdHandler のルーム設定を迂回される可能性があります。
シナリオ 2 - API エンドポイントでは、 異なる 保護対象のサイトからのドメイン。
例
保護対象ドメイン-https://tickets.example.com
APIエンドポイント-https://datasource.com/v1/api
CrowdHandler のルーム設定
- CrowdHandlerのルームを設定する際は、APIドメインではなく、サイトのドメイン(https://tickets.example.com)を保護するようにしてください。
- エンドユーザーが需要の高い商品をカートに追加するページは、保護する必要があります。
- ルームの設定は、保護対象のドメイン上のURLと一致している必要があります。
導入手順
APIリクエストのペイロードを変更する
「カートに追加」APIルートのペイロードに、以下の2つのフィールドを追加してください。 キー:sourceURL 値:location.href(API呼び出しを行っている保護されたページのURL) キー:chToken 値:CrowdHandlerトークン(統合タイプに応じて、クッキーまたはローカルストレージから取得されます)。
リクエストをサーバー側で検証する。
const urlParts = new URL(params.sourceURL);
const token = params.chToken;
const crowdhandler = require('crowdhandler-sdk');
const mockRequest = {
getHost: () => urlParts.host,
getPath: () => urlParts.pathname,
getCookies: () => `crowdhandler=${token}`
};
const { gatekeeper } = crowdhandler.init({
publicKey: 'your-public-key',
request: mockRequest,
response: {}, // Empty object is fine for validation only
});
const result = await gatekeeper.validateRequest();
// ✅ This works!
// result.promoted = true/false
// Reject if false ❌
// result.error = { message, statusCode, code } (if error occurred)