2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CSRF トークンをfetchのヘッダーに載せる

2
Posted at

Blade(サーバーサイド)の中に React コンポーネント(クライアントサイド)を組み込むという前提で進めます。

この構成で fetch を使って POST リクエストを送る場合、「Blade 側(サーバー)が生成した CSRF トークンを、JavaScript(React)側へ渡して fetch のヘッダーにセットする」です。

🔄 全体の処理の流れ(概要図)

  1. 【Blade】 ページ表示時に、CSRF トークンを meta タグに埋め込んでおく。
  2. 【React】 画面が読み込まれたら、JavaScript で meta タグからトークンを読み取る。
  3. 【React】 fetch で POST 送信する際、リクエストヘッダー(X-CSRF-TOKEN)にそのトークンを乗せる。
  4. 【サーバー】 届いたヘッダーのトークンを検証し、問題なければ処理を実行する。

💻 具体的なコードと実装ステップ

ステップ 1. 【Blade 側】meta タグにトークンを仕込む

まず、React コンポーネントを読み込んでいるベースの Blade ファイル(index.blade.php など)の <head> タグ内に、CSRF トークンを出力する meta タグを記述します。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <title>マイアプリ</title>
</head>
<body>
    <div id="app"></div>

    @vite(['resources/js/app.jsx'])
</body>
</html>

ステップ 2. 【React 側】fetch のヘッダーにトークンをセットして POST する

次に、React コンポーネント側で fetch を使ってリクエストを送る処理です。JavaScript で先ほどの meta タグから値を取得し、ヘッダーに X-CSRF-TOKEN という名前でセットします。

import React, { useState } from 'react';

export const SendMoneyForm = () => {
  const [amount, setAmount] = useState('');

  const handleSubmit = async (e) => {
    e.preventDefault();

    // 1. HTMLの <meta name="csrf-token"> からトークンの値を取得する
    const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');

    try {
      // 2. fetch で POST リクエストを送信
      const response = await fetch('/api/send-money', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          // サーバーが検証できるようにヘッダーにトークンを入れる
          'X-CSRF-TOKEN': csrfToken, 
        },
        body: JSON.stringify({ amount: amount }),
      });

      if (response.ok) {
        alert('送金が完了しました!');
      } else {
        alert('エラーが発生しました(トークンエラーの可能性あり)');
      }
    } catch (error) {
      console.error('通信失敗:', error);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input 
        type="number" 
        value={amount} 
        onChange={(e) => setAmount(e.target.value)} 
        placeholder="金額を入力"
      />
      <button type="submit">送金する</button>
    </form>
  );
};

ステップ 3. 【サーバー側】自動検証

リクエストがサーバー(バックエンド)に届くと、Webフレームワークが持つ「CSRF検証ミドルウェア」が自動的に働きます。

  • サーバーは、届いたリクエストのヘッダーにある X-CSRF-TOKEN をチェックします。
  • サーバーがセッションに保持しているトークンと一致すれば、コントローラーの処理(データの保存など)へ進めます。
  • トークンが古い、あるいは存在しない場合は、一歩も中に入れずに 419 Unknown Status(または 403 Forbidden などのエラーを返してリクエストを遮断します。
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?