カテゴリ: Spring認証(Spring Security) 更新日: 2026/02/19

CSRF対策の基本的な仕組みとは?初心者向けにわかりやすく解説

CSRF対策の基本的な仕組み
CSRF対策の基本的な仕組み

新人と先輩の会話形式で理解しよう

新人

「Webセキュリティの勉強をしていたら『CSRF』って言葉が出てきたんですけど、それって何なんですか?」

先輩

「CSRFは『クロスサイトリクエストフォージェリ』と呼ばれる攻撃手法の一つで、ユーザーの意図しない操作をWebアプリケーションにさせる危険な仕組みだよ。」

新人

「ユーザーが知らないうちに操作されるってことですか?どんな感じなんでしょう?」

先輩

「それじゃあ、CSRF攻撃の基本と仕組みを順番に解説していこう!」

1. CSRF(クロスサイトリクエストフォージェリ)とは?

1. CSRF(クロスサイトリクエストフォージェリ)とは?
1. CSRF(クロスサイトリクエストフォージェリ)とは?

CSRFとは、「Cross-Site Request Forgery(クロスサイトリクエストフォージェリ)」の略で、日本語では「サイト間リクエスト偽造」と呼ばれます。これは、ログイン中のユーザーが意図しない操作をさせられる攻撃です。

例えば、ユーザーがログインしたままの状態で、悪意あるサイトにアクセスしたときに、攻撃者が用意したリクエストが自動的に送信され、ユーザーが意図しない更新や削除操作が実行されることがあります。

CSRFは、ユーザーの「信頼されたセッション情報(クッキーなど)」を利用して、正規のリクエストを偽装するのが特徴です。だからこそ、Webアプリケーション側でCSRF対策が重要になります。

2. なぜWebアプリケーションにとって危険なのか

2. なぜWebアプリケーションにとって危険なのか
2. なぜWebアプリケーションにとって危険なのか

CSRF攻撃が危険な理由は、攻撃者がユーザーの認証情報を悪用して「正規の操作」としてリクエストを送信できてしまう点にあります。

たとえば、ユーザーがインターネットバンキングにログインした状態で、別の悪質なサイトを閲覧するとします。すると、その悪質なサイトに仕込まれたスクリプトが、自動的に振込処理を行うリクエストを銀行に送るということが可能になります。

このとき、Webアプリ側が「このリクエストは本当にユーザーが意図したものか」を確認できないと、重大な被害につながります。だからこそ、CSRF対策はWebセキュリティにおいて非常に重要な位置づけになります。

3. 実際にどういった攻撃シナリオが考えられるのか(簡単な例)

3. 実際にどういった攻撃シナリオが考えられるのか(簡単な例)
3. 実際にどういった攻撃シナリオが考えられるのか(簡単な例)

ここでは、CSRF攻撃がどのように行われるかの簡単な例を紹介します。以下は、攻撃者が自分のWebサイトに以下のようなHTMLを埋め込んだケースです。


<form action="http://example.com/user/update-email" method="POST">
  <input type="hidden" name="email" value="hacker@example.com" />
  <input type="submit" value="送信" />
</form>
<script>
  document.forms[0].submit();
</script>

このHTMLは、あるユーザーが攻撃者のWebサイトを開いたときに自動的にフォームが送信されて、メールアドレスが「hacker@example.com」に変更されてしまうという仕組みです。

もしこのとき、ユーザーがexample.comにログインしていて、セッション情報(クッキー)がブラウザに残っていれば、攻撃が成立してしまいます。

このような攻撃は、フォーム以外にも、画像タグやリンクなど、さまざまな手段で実行可能です。そのため、すべてのPOSTリクエストに対してCSRF対策が必要になります。

4. CSRF対策がSpring Securityに標準で組み込まれていることの紹介

4. CSRF対策がSpring Securityに標準で組み込まれていることの紹介
4. CSRF対策がSpring Securityに標準で組み込まれていることの紹介

Spring Securityでは、CSRF対策が最初から有効になっているため、特別な設定をしなくても、基本的な保護が働きます。これは、Spring Securityがセキュリティに強い理由の一つであり、開発者がミスをしにくい設計になっています。

たとえば、Spring BootプロジェクトにSpring Securityを追加した場合、POST・PUT・DELETEといった状態を変更するようなリクエストに対して、CSRFトークンが自動的にチェックされるようになります。

この仕組みにより、攻撃者が偽のフォームを送信しても、正しいトークンが含まれていなければリクエストは拒否されます。つまり、Spring Securityは初期状態でCSRFトークンによる保護を行うのです。

逆に言えば、CSRFトークンがフォームに含まれていない場合、Spring Securityによって403エラーが返されることになります。

5. Spring SecurityのCSRF対策の有効化とデフォルトの挙動

5. Spring SecurityのCSRF対策の有効化とデフォルトの挙動
5. Spring SecurityのCSRF対策の有効化とデフォルトの挙動

Spring Securityでは、CSRF対策がデフォルトで有効になっていますが、設定の確認やカスタマイズも可能です。Spring Bootを使った場合、以下のようにセキュリティ設定クラスを作成して確認できます。


@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authz -> authz
                .requestMatchers("/").permitAll()
                .anyRequest().authenticated()
            )
            .csrf(Customizer.withDefaults()); // CSRF対策をデフォルト有効化
        return http.build();
    }
}

上記のように、csrf(Customizer.withDefaults())を記述することで、Spring Securityが持つCSRF保護機能をそのまま有効にできます。この状態では、POSTやPUTなどのリクエストで、CSRFトークンが一致しないと403エラーになります。

フォーム画面では、トークンをHTMLに埋め込む必要があるため、後述の方法でトークンを自動挿入する工夫が求められます。

6. CSRFトークンの仕組み(生成・検証・送信の流れ)

6. CSRFトークンの仕組み(生成・検証・送信の流れ)
6. CSRFトークンの仕組み(生成・検証・送信の流れ)

CSRF対策の核となるのが「CSRFトークン」です。これは、Webアプリケーションがユーザーごとに一意の値を発行し、それをフォームに埋め込むことで、正規のリクエストかどうかを判断する仕組みです。

Spring Securityでは、CSRFトークンはリクエストごとに自動生成され、セッションに紐付けられて保存されます。そして、フォームが描画されるタイミングで、そのトークンをHTMLの中に埋め込むことが求められます。

例えば、次のようなHTMLフォームでCSRFトークンを送信する必要があります。


<form method="post" action="/account/update">
  <input type="hidden" name="_csrf" value="${_csrf.token}" />
  <input type="text" name="username" />
  <button type="submit">更新</button>
</form>

上記のように_csrfという名前のhiddenフィールドに、CSRFトークンをセットして送信します。Spring Securityは、リクエストを受け取った際に、このトークンがセッションに保存されているものと一致するかを検証します。

一致していればリクエストを許可し、不一致や未指定の場合は403 Forbiddenエラーとなります。これにより、不正な外部サイトからのリクエストが弾かれる仕組みになっているのです。

CSRFトークンは、フォームからだけでなく、JavaScriptを使ったAjax通信にも必要です。その場合、HTTPヘッダーにトークンを埋め込むなどの工夫が必要になります。

たとえば、Ajaxで送信する際は、次のようにトークンをヘッダーに含めることが一般的です。


<script>
  const csrfToken = document.querySelector('meta[name="_csrf"]').getAttribute('content');
  fetch('/api/update', {
    method: 'POST',
    headers: {
      'X-CSRF-TOKEN': csrfToken,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ key: 'value' })
  });
</script>

このように、CSRF対策では「どのようにトークンを埋め込み、送信し、検証するか」をきちんと理解しておくことが非常に重要です。

CSRFトークンは、セッションと結びついていて、第三者が推測できない値であるため、セキュリティレベルを高める有効な手段となります。

Spring Securityは、これらのトークン処理を自動で行ってくれる仕組みが備わっているため、適切に使えば高い安全性を確保することが可能です。

7. カスタマイズしたCSRF設定(特定のエンドポイントを除外する方法など)

7. カスタマイズしたCSRF設定(特定のエンドポイントを除外する方法など)
7. カスタマイズしたCSRF設定(特定のエンドポイントを除外する方法など)

Spring SecurityのCSRF対策は強力ですが、すべてのエンドポイントに対して一律に適用されるわけではありません。開発中や一部のAPI連携では、特定のパスだけCSRF保護を除外したいケースもあります。

たとえば、外部サービスからのPOSTリクエストを受けたい場合や、Webhook連携などでは、トークンの確認が難しいことがあります。このような場合は、セキュリティ設定で「CSRFトークン除外」の対象を個別に指定できます。


@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authz -> authz
                .requestMatchers("/").permitAll()
                .anyRequest().authenticated()
            )
            .csrf(csrf -> csrf
                .ignoringRequestMatchers("/webhook/**") // CSRFトークンを除外
            );
        return http.build();
    }
}

ignoringRequestMatchers()を使えば、CSRF制御の対象外としたいURLパターンを指定できます。上記の例では、/webhook/**パス以下のリクエストはCSRFトークンなしでも許可されます。

ただし、このような除外設定を安易に増やすとセキュリティリスクが高まります。特に認証が必要な管理系のAPIを除外するのは、アンチパターンです。CSRFトークン除外は、必ず「必要最小限の安全な範囲でのみ」行うようにしましょう。

8. 実際のフォームでCSRFトークンを扱う方法(Thymeleafなどを使わず基本的なformで解説)

8. 実際のフォームでCSRFトークンを扱う方法(Thymeleafなどを使わず基本的なformで解説)
8. 実際のフォームでCSRFトークンを扱う方法(Thymeleafなどを使わず基本的なformで解説)

実際のWeb画面で、CSRFトークンを正しく送信するためには、HTMLのフォームに手動でトークンを埋め込む必要があります。Thymeleafなどのテンプレートエンジンを使っていない場合は、コントローラ側でトークン情報をビューに渡すことで対応します。

Spring Securityでは、CsrfTokenオブジェクトを取得して、モデルに追加することで、フォーム内で使用できます。


@Controller
public class FormController {

    @GetMapping("/form")
    public String showForm(Model model, CsrfToken token) {
        model.addAttribute("_csrf", token);
        return "form";
    }
}

このようにCsrfTokenを受け取ることで、HTML内にトークンを埋め込むことができます。ビュー(form.htmlなど)では、以下のようにhiddenフィールドを記述します。


<form method="post" action="/submit">
  <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
  <input type="text" name="username" />
  <button type="submit">送信</button>
</form>

ポイントは、_csrf.parameterName_csrf.tokenを適切に出力することです。これにより、Spring Securityが期待するパラメータ名とトークン値が正しく送信され、CSRF検証が成功します。

初心者のうちはトークンの取得方法や名前の扱いでつまずきやすいですが、必ずhiddenフィールドとしてトークンを明示的に送信することを意識しましょう。

9. CSRFを無効化した場合のリスクや注意点

9. CSRFを無効化した場合のリスクや注意点
9. CSRFを無効化した場合のリスクや注意点

開発中やデバッグ中に、403 Forbiddenエラーが出て動かなくなると、「CSRF無効化すればいいのでは?」という考えが浮かびがちです。しかし、これは非常に危険な選択です。

CSRF対策を無効にすると、攻撃者がユーザーのセッションを利用して、不正な操作を実行することが可能になります。たとえば、以下のような設定はセキュリティ的に問題があります。


// ※やってはいけない例(アンチパターン)
http.csrf(csrf -> csrf.disable());

この設定により、全てのリクエストに対してCSRFチェックが無効化されます。つまり、攻撃者が偽装リクエストを送ってもブロックされなくなってしまいます。特にログイン後の機能(会員情報更新や購入処理など)があるシステムでは、被害が深刻化する可能性があります。

どうしても一時的に無効化が必要な場合でも、開発用の環境だけに限定し、本番環境では必ず有効に戻すようにしてください。

Spring Securityは、CSRFトークンを自動で管理してくれるため、基本的にはその仕組みに乗っかるだけで安全性が高まります。CSRFトークン除外やCSRF無効化のリスクを正しく理解し、安易にdisable()を使わないことがWebアプリの信頼性向上につながります

まとめ

まとめ
まとめ

ここまで、Webアプリケーションのセキュリティにおいて避けては通れない「CSRF(クロスサイトリクエストフォージェリ)」の仕組みと、その対策の要となるSpring Securityの役割について詳しく解説してきました。Webエンジニアとして開発に携わる際、CSRFはSQLインジェクションやクロスサイトスクリプティング(XSS)と並んで、必ず理解しておくべき脆弱性の一つです。

CSRF攻撃の恐ろしさは、「ユーザーが気づかないうちに、正規のログインセッションが悪用される」という点にあります。悪意のある第三者が用意した罠サイトを踏むだけで、パスワードの変更や商品の購入、SNSへの投稿といった操作が勝手に実行されてしまうのです。こうした攻撃を防ぐために、現代のWeb開発では「CSRFトークン」という、リクエストごとに生成される使い捨ての識別子を用いるのが一般的です。

Spring Securityを活用した堅牢なシステム構築

Spring BootとSpring Securityを導入しているプロジェクトであれば、デフォルトでこのCSRF対策が有効になっています。これは非常に強力な機能ですが、一方で「POSTリクエストを投げると理由がわからず403エラーになる」といった初心者特有の悩みを生む原因にもなります。しかし、そのエラーこそがSpring Securityがあなたのアプリケーションを必死に守ってくれている証拠でもあります。

実際の現場で実装する際は、単に機能を有効にするだけでなく、Thymeleafなどのテンプレートエンジンとの連携や、JavaScript(Ajax/Fetch API)を用いた非同期通信時のヘッダー制御など、状況に応じた柔軟な対応が求められます。特にAPIサーバーとして構築する場合や、外部ツールとのWebhook連携を行う場合には、特定のパスを除外する設定も必要になるでしょう。

実装のポイント:CSRFトークンの送信サンプル

復習として、独自のHTMLフォームでCSRFトークンを確実に送信する実装例を再確認しておきましょう。Spring Securityから渡されたトークンを、以下のようにhidden属性のinputタグで埋め込むのが基本です。


<form action="/update-profile" method="POST" class="p-3 border rounded">
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
    
    <div class="mb-3">
        <label for="nickname" class="form-label">新しいニックネーム</label>
        <input type="text" id="nickname" name="nickname" class="form-control" />
    </div>
    
    <button type="submit" class="btn btn-primary">プロフィールを更新する</button>
</form>

Java側の設定クラスでも、安全性を確保しつつ利便性を損なわない設定を心がけることが大切です。以下のコードは、セキュリティを維持しながら特定のエンドポイント(例:外部通知用URL)だけを除外する、実務でよく使われるカスタマイズ例です。


@Configuration
@EnableWebSecurity
public class WebSecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authorize -> authorize
                .requestMatchers("/public/**", "/login").permitAll()
                .anyRequest().authenticated()
            )
            .csrf(csrf -> csrf
                // セキュリティ上、除外は最小限に留めるのが鉄則
                .ignoringRequestMatchers("/api/external-callback/**")
            );
        
        return http.build();
    }
}

最後に、セキュリティ対策に「銀の弾丸」はありません。CSRF対策を有効にするのはもちろんのこと、CookieにSameSite属性を適切に設定したり、不要な権限を与えないといった多層的な防御意識を持つことが、信頼されるWebサービスの第一歩となります。

先生と生徒の振り返り会話

生徒

「先生、ありがとうございました!CSRFって、ただ『悪い奴に操作される』ってだけじゃなくて、ブラウザの『ログイン情報を勝手に送っちゃう』っていう仕組みを逆手に取った攻撃なんですね。だからトークンを埋め込んで、本人からの正規の送信か確認する必要があるんだ、と納得しました。」

先生

「その通り!よく理解できたね。ブラウザは親切にもクッキーを自動で送ってくれるけど、それが仇になることもあるんだ。だから、サーバー側で『このリクエストには合言葉(トークン)が入っているか?』をチェックするのが一番確実なんだよ。」

生徒

「実は以前、POST送信をした時に403エラーが出て、解決策がわからなくてcsrf().disable()って書いて無理やり通しちゃったことがあるんです……。今思うと、家の鍵を全部開けっ放しにするくらい危険なことだったんですね。」

先生

「ははは、それは初心者が一番通る道だね。でも今日でそのリスクは理解できたはず。Spring Securityを使えば、hiddenタグを一つ入れるだけで安全が手に入るんだから、これからはしっかりトークンを活用していこう。Ajax通信のときもヘッダーにセットするのを忘れないようにね!」

生徒

「はい!これからは安易に無効化せず、正しくトークンを扱う実装を心がけます。セキュリティを味方につけて、安心安全なアプリを作れるようになりたいです!」

この記事を読んだ人からの質問

この記事を読んだ人からの質問
この記事を読んだ人からの質問

プログラミング初心者からのよくある疑問/質問を解決します

CSRF(クロスサイトリクエストフォージェリ)とは、具体的にどのような攻撃手法のことを指すのでしょうか?

CSRFは「Cross-Site Request Forgery」の略称で、日本語では「サイト間リクエスト偽造」と訳される非常に危険なWebセキュリティ上の攻撃手法です。この攻撃の最大の特徴は、ログイン中のユーザーが「自分では気づかないうちに、意図しない操作をWebアプリケーション上で実行させられてしまう」という点にあります。例えば、ユーザーがSNSやインターネットバンキングにログインしたまま、悪意のあるプログラムが仕込まれた別のサイトにアクセスした際、そのサイトから自動的に「パスワード変更」や「送金リクエスト」などの命令が正規のサービスへ送られてしまいます。ブラウザが自動的にクッキーなどのセッション情報を送信してしまう仕組みを悪用するため、Webアプリ側はそれが本人の操作か、攻撃者による偽造されたリクエストかを見分けることが難しくなります。そのため、開発者は必ずCSRF対策を実装して、システムの安全性を確保しなければなりません。
コメント
コメント投稿は、ログインしてください

まだ口コミはありません。

カテゴリの一覧へ
新着記事
New1
Springの基本
Spring Bootの@ConfigurationPropertiesScanとは?設定クラス自動検出の仕組みを解説
New2
SpringのAPI開発(REST & GraphQL)
Spring Boot GraphQLでResolverを理解しよう!初心者でもわかるデータ取得の基本
New3
SpringのAPI開発(REST & GraphQL)
Spring Boot GraphQL入門!Query・Mutation・Subscriptionの基本を初心者向けに解説
New4
SpringのDB操作
JPQLのパラメータバインド(:name / ?1)の使い方を完全解説!初心者でも迷わない基本の考え方
人気記事
No.1
Java&Spring記事人気No1
Thymeleaf
Thymeleaf とは?初心者向けにThymeleafの基本を徹底解説
No.2
Java&Spring記事人気No2
SpringのWeb開発(Spring MVC)
DispatcherServletの仕組みを理解する!初心者向け完全ガイド
No.3
Java&Spring記事人気No3
Springの基本
Spring Bootのデフォルトログ設定を徹底解説(Logback / SLF4J)
No.4
Java&Spring記事人気No4
SpringのDB操作
JPAの標準クエリメソッド(findById, findAll)を完全解説!初心者でもわかるデータ取得の基本
No.5
Java&Spring記事人気No5
SpringのWeb開発(Spring MVC)
Spring Bootでの@GetMappingと@PostMappingの基本を完全解説!初心者でも理解できる使い方
No.6
Java&Spring記事人気No6
Spring認証(Spring Security)
セッション管理の基本(@SessionAttributes)を完全解説!初心者でもわかるセッションの仕組み
No.7
Java&Spring記事人気No7
SpringのWeb開発(Spring MVC)
@Controller と @RestController の違いを完全解説!初心者向けSpring MVC入門
No.8
Java&Spring記事人気No8
SpringのWeb開発(Spring MVC)
ループ処理(th:each)の基本を完全ガイド!Thymeafの繰り返し処理の使い方