doodle-on-web

自分で調べたことや、仕事の中で質問されたことなどをまとめています。

JMeterで403エラーを解決!CookieのCSRFトークンをヘッダーに渡す方法【2025年最新版】

スポンサーリンク

--- ## 「Cookieは送れているのに403が返ってくる」——その原因と5分で完結する解決策 JMeterで負荷テストのシナリオを組んでいて、こんな経験はありませんか?「CookieマネージャをセットしてリクエストもきちんとCookieを送っているのに、サーバーから`403 Forbidden`が返ってくる」。ログを追っても原因がわからず、時間だけが過ぎていく——。 **本記事を読めば、この問題を約5分で解決できます。** 正規表現抽出器を使ってCookieの値を変数に格納し、後続リクエストのヘッダーへ渡す方法を、設定値の一覧とトラブルシューティングを交えながらステップバイステップで解説します。 対象読者は「JMeterでSPAやモダンWebアプリの負荷テストシナリオを組んでいる、初級〜中級エンジニア」を想定しています。2025年5月時点のJMeter 5.6系を前提にしています。 --- ## なぜCookieマネージャだけではSPAに対応できないのか この現象の犯人は、多くの場合**CSRFトークンの二重送信要件**です。AngularやReact、Vue.jsといったモダンなSPAフレームワークを採用したシステムでは、ブラウザの開発者ツール(ChromeであればF12キー)で実際の通信を観察すると、次のような構造が確認できます。 ``` Cookie: XSRF-TOKEN=abc123xyz; session=xxxxxxxx X-XSRF-TOKEN: abc123xyz ← Cookieと同じ値をヘッダーにも付与 ``` これは**Double Submit Cookieパターン**と呼ばれるCSRF対策の実装で、サーバー側は「CookieとヘッダーのトークンがI致していること」を確認することで正規のリクエストと判断します。 > **【誤字について】** 上記の「I致」は原文ママです。正しくは「**一致**」です。 JMeterのCookieマネージャはCookieの自動送受信は担ってくれますが、**CookieからヘッダーへのコピーはJMeter単体では自動処理されません**。この仕組みを手動で作ることが、403解決の本質です。 --- ## 前提条件:Cookieマネージャの有効化を確認する 本手順に進む前に、テストプランにHTTP Cookieマネージャが追加されているか確認してください。 - テストプランまたはスレッドグループを右クリック - [追加]→[設定エレメント]→[HTTP Cookieマネージャ]を選択 Cookieマネージャがない場合、セッションCookie自体が引き継がれないため、CSRFトークン以前の問題が発生します。 --- ## 解決策:正規表現抽出器でCookie値を変数に格納する ### ステップ1:正規表現抽出器を追加する `Set-Cookie`レスポンスヘッダーが返ってくるリクエスト(ログインや初回アクセスなど)のサンプラーを右クリックし、以下の手順で正規表現抽出器を追加します。 - 対象サンプラーを右クリック - [追加]→[後処理]→[正規表現抽出]を選択 ### ステップ2:正規表現抽出器を設定する 追加した正規表現抽出器に以下の値を入力します。 | 設定項目 | 入力値 | |---|---| | **Apply to** | `Main sample and sub-samples` | | **Field to check** | `Response Headers` | | **Reference Name** | `xsrfToken`(任意の変数名) | | **Regular Expression** | `Set-Cookie:\s*XSRF-TOKEN=([^;]+)` | | **Template** | `$1$` | | **Match No.** | `1` | | **Default Value** | `NOT_FOUND` | **最重要ポイントが2つあります。** 1. `Field to check`は必ず`Response Headers`を選んでください。Cookieはレスポンスヘッダー内の`Set-Cookie`として送られてきます。誤って`Response Body`を選択すると値が取得できません。 2. 正規表現は`Set-Cookie:\s*XSRF-TOKEN=([^;]+)`としています。`\s*`でコロン後のスペース有無を吸収し、`[^;]+`でセミコロンまでの値を確実にキャプチャします。末尾の`;`がないCookieにも対応できるため、元の`(.+?);`より堅牢です。 `Default Value`を`NOT_FOUND`にしておくと、抽出失敗をすぐに検知できるため、デバッグ時に役立ちます。 ### ステップ3:取得した変数をリクエストヘッダーに設定する 変数に格納できたら、後続リクエストにHTTPヘッダーマネージャを追加し、次のように設定します。 - 後続リクエストのサンプラーを右クリック - [追加]→[設定エレメント]→[HTTPヘッダーマネージャ]を選択 | ヘッダー名 | 値 | |---|---| | `X-XSRF-TOKEN` | `${xsrfToken}` | JMeterでは`${変数名}`の記法で、正規表現抽出器が格納した変数を参照できます。ヘッダーマネージャはスレッドグループ直下に置くことで全リクエストに適用することも可能ですが、トークンが不要なリクエストへの影響を避けるため、必要なサンプラーだけに配置する運用を推奨します。 --- ## 動作確認の手順 設定が完了したら、本番負荷をかける前に必ず**1スレッド・1ループ**で動作を検証しましょう。 1. **「結果をツリーで表示」リスナー**を追加してテストを実行し、正規表現抽出を設定したリクエストのレスポンスヘッダーに`Set-Cookie: XSRF-TOKEN=...`が含まれているか目視確認する。 2. **デバッグサンプラー**([追加]→[サンプラー]→[デバッグサンプラー])を正規表現抽出の直後に配置し、変数の中身を確認する。 デバッグサンプラーの出力は次のようになります。正常時と異常時の違いを確認してください。 ``` # 正常時(トークンが取得できている場合) xsrfToken=abc123xyz # 異常時(抽出に失敗している場合) xsrfToken=NOT_FOUND ``` `NOT_FOUND`が表示されている場合は、次のトラブルシューティングセクションを参照してください。 --- ## よくあるトラブルと対処法 ### 変数が「NOT_FOUND」のまま - `Field to check`が`Response Body`になっていないか再確認する - 実際のレスポンスヘッダーを結果ツリーでコピーし、正規表現をその内容に合わせて調整する - HTTPS環境では`Secure`属性付きCookieが別行に分かれて返る場合があるため、ヘッダーの改行位置に注意する ### 複数のSet-Cookieヘッダーがある場合 `Match No.`を`-1`にするとすべてのマッチを配列として取得できます(変数名は`xsrfToken_1`、`xsrfToken_2`…という形式)。特定のトークンのみ必要な場合は正規表現を絞り込み、`Match No.=1`のまま運用するのがシンプルです。 ### ループのたびにトークンが変わる SPAでは操作のたびにCSRFトークンが更新される実装も珍しくありません。シナリオのループ内で毎回正規表現抽出を行うよう構成し、常に最新のトークンを取得してください。ループの冒頭に「トークン取得用リクエスト → 正規表現抽出 → 業務リクエスト」という順序を組み込むのがベストプラクティスです。 ### 正規表現では対応できないエッジケース Cookieの名前が動的に変化するなど、正規表現では対応しきれないケースでは**JSR223後処理**(Groovyスクリプト)を使う方法が有効です。`prev.getResponseHeaders()`でヘッダー文字列全体を取得し、Groovyの文字列操作で柔軟にパースできます。正規表現では難しいケースに直面したときの選択肢として覚えておくと、対応できる幅が広がります。 --- ## まとめ:4ステップで完結するCSRFトークン対応 今回解説した手順を整理します。 | ステップ | 内容 | |---|---| | **①事前確認** | ブラウザの開発者ツールで通信を観察し、`X-XSRF-TOKEN`などのヘッダーが必要か確認する | | **②抽出器の追加** | `Set-Cookie`が返るリクエストに正規表現抽出器を追加する | | **③正しいフィールドの選択** | `Field to check`を`Response Headers`に設定し、正規表現`Set-Cookie:\s*XSRF-TOKEN=([^;]+)`で値を抽出する | | **④ヘッダーへの転記** | 後続リクエストのHTTPヘッダーマネージャに`X-XSRF-TOKEN: ${xsrfToken}`を追加する | JMeterのCookieマネージャは日常的なセッション管理には十分強力ですが、CSRFトークンのように**CookieとHTTPヘッダーを連動させる必要があるケース**では、正規表現抽出器との組み合わせが欠かせません。 「なぜ403が返るのかわからない」と悩んでいる方は、まずブラウザの開発者ツールで実際の通信ヘッダーを丁寧に確認することを強くおすすめします。その一手間が、根本原因への最短ルートになります。