Spring BootでCORSを設定する方法を完全解説!初心者でもわかるセキュリティ対策
新人
「先輩、フロントエンドのReactアプリからSpring BootのAPIにアクセスしたら、CORSエラーが出たんですが……どうすればいいんでしょうか?」
先輩
「それはCORS(Cross-Origin Resource Sharing)の制限に引っかかってるね。セキュリティの仕組みだから、まずはCORSとは何かを理解しよう。」
新人
「クロスオリジンって言葉は聞いたことありますけど、正直よくわかってないです……。」
先輩
「大丈夫。CORSの仕組みと、Spring BootでのCORS設定方法を順を追って説明していくよ。」
1. CORSとは何か?
「CORS」とは「Cross-Origin Resource Sharing(クロスオリジン・リソース・シェアリング)」の略で、セキュリティの観点から用意されたHTTPの仕組みです。
Webブラウザには、同一オリジンポリシーというセキュリティルールがあります。これは、あるWebページから読み込んだJavaScriptが、別のオリジン(スキーム・ドメイン・ポートの組み合わせが異なるもの)に勝手にアクセスすることを禁止するというルールです。
たとえば、以下のようなケースではオリジンが異なると判断され、通常のHTTP通信ではブロックされてしまいます。
http://localhost:3000(フロントエンド)http://localhost:8080(Spring Bootバックエンド)
このようなクロスオリジン通信を許可するために導入された仕組みがCORSです。クライアント(ブラウザ)は、HTTPリクエスト時にOriginというヘッダーを付けて送信し、サーバーがそれを確認してレスポンスヘッダーで「このリクエストを受け付ける」と明示的に返すことで通信が成立します。
つまり、CORSとはセキュリティ対策の一部であり、意図しないアクセスや悪意のあるスクリプトからサーバーを保護するための重要な仕組みです。
2. Spring BootでCORSを設定する理由
Spring BootでWebアプリケーションやAPIを構築している場合、フロントエンドアプリケーションと別のポート・ドメインで動作することが一般的です。たとえば、フロントエンドはhttp://localhost:3000でReactやVue、バックエンドのSpring Bootはhttp://localhost:8080で動作しているとします。
このとき、JavaScriptがバックエンドにHTTPリクエストを送ると、ブラウザはクロスオリジンの制限を検出して通信をブロックします。この通信を正常に動かすには、サーバー側でCORSを許可する設定が必要です。
Spring Bootでは、CORS設定をコントローラ単位やグローバル設定で行うことができ、必要なリクエストのみ許可することでセキュリティを確保しながら柔軟な通信が可能になります。
2-1. コントローラ単位でのCORS許可
以下は@CrossOriginアノテーションを使って、特定のオリジンからのアクセスを許可する例です。
@Controller
@RequestMapping("/api")
public class SampleController {
@CrossOrigin(origins = "http://localhost:3000")
@GetMapping("/message")
@ResponseBody
public String getMessage() {
return "CORS設定が成功しました";
}
}
このように設定することで、http://localhost:3000からのアクセスに対してのみレスポンスを返すようになります。他のオリジンからのアクセスはブロックされるため、安全性も確保されます。
2-2. グローバルなCORS設定が必要な場合
複数のエンドポイントで同じCORS設定をしたい場合、コントローラごとに@CrossOriginを記述するのは非効率です。その場合は、Spring Securityの設定クラスを用いてグローバルにCORSポリシーを定義します。これは次のセクションで詳しく紹介します。
3. JavaでCORSを許可するコード例(@Controller+SecurityConfig)
ここでは、Spring Bootアプリケーションにおいて、@Controller構成を前提とした「グローバルなCORS設定方法」を紹介します。特に、Spring Securityを使用している場合は、CORS設定をSecurityConfigクラスに記述するのが一般的です。
まずは、WebSecurityConfigurerAdapterを継承したセキュリティ設定クラスを作成し、CORSを許可する構成にします。
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors() // CORSを有効化
.and()
.csrf().disable(); // 開発用としてCSRFは無効化
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true); // 認証情報の送信を許可
config.addAllowedOrigin("http://localhost:3000"); // 許可するオリジン
config.addAllowedHeader("*"); // すべてのヘッダーを許可
config.addAllowedMethod("*"); // すべてのHTTPメソッドを許可
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config); // 全エンドポイントに適用
return source;
}
}
このコードでは、http://localhost:3000からのリクエストに対して、すべてのヘッダーとHTTPメソッド(GET、POSTなど)を許可しています。加えて、setAllowCredentials(true)を指定することで、クッキーやセッションIDなどの認証情報のやり取りも可能になります。
注意点として、Access-Control-Allow-Originに*を指定しながらsetAllowCredentials(true)を使うことはできません。必ず明示的にオリジンを指定しましょう。
4. Spring Securityを使ったCORS設定(Filterまたは設定クラスで制御する方法)
先ほど紹介した方法は、Spring Securityの設定クラスでCORSを一括設定する方法でしたが、より柔軟に制御したい場合は、CORS専用のフィルターを自作してSpring Bootに組み込むことも可能です。
以下は、Javaで独自のCORSフィルタークラスを作成し、@Bean登録する方法です。
@Configuration
public class CorsFilterConfig {
@Bean
public FilterRegistrationBean<CorsFilter> corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("http://localhost:3000");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
bean.setOrder(0); // 最も早い順序で実行
return bean;
}
}
この方法では、SecurityConfigと分離してCORSポリシーを設定できるため、責任範囲が明確になります。また、URLごとに異なるポリシーを定義しやすくなるというメリットもあります。
ただし、Spring Securityの設定でhttp.cors()を有効にすることを忘れずに行う必要があります。フィルターだけを登録しても、Security側でCORSをブロックしてしまうと効果がありません。
5. パスごとに異なるCORSポリシーを設定する方法(URL別設定)
APIごとに異なるCORS設定をしたいケースもあるでしょう。たとえば、認証用APIは特定のドメインからしか許可せず、公開APIはすべてのオリジンに開放するといったケースです。
Spring Bootでは、URLパターンごとにCORSポリシーを定義することが可能です。以下はその具体例です。
@Configuration
public class MultiCorsConfig {
@Bean
public CorsConfigurationSource corsConfigurationSource() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
// 認証系APIは1つのオリジンのみ許可
CorsConfiguration authConfig = new CorsConfiguration();
authConfig.setAllowCredentials(true);
authConfig.addAllowedOrigin("https://secure.example.com");
authConfig.addAllowedMethod("*");
authConfig.addAllowedHeader("*");
source.registerCorsConfiguration("/api/auth/**", authConfig);
// 公開APIは複数のオリジンから許可
CorsConfiguration publicConfig = new CorsConfiguration();
publicConfig.setAllowCredentials(false);
publicConfig.addAllowedOrigin("http://localhost:3000");
publicConfig.addAllowedOrigin("https://public.example.com");
publicConfig.addAllowedMethod("*");
publicConfig.addAllowedHeader("*");
source.registerCorsConfiguration("/api/public/**", publicConfig);
return source;
}
}
このようにregisterCorsConfiguration()で特定のURLパターンを指定することで、APIごとに異なるCORS設定を適用できます。
開発段階ではオリジンの制限を緩め、本番環境ではセキュリティ強化のためにオリジンを厳しく制限するという運用も可能です。
このような「パス別のSpring Boot CORS設定方法」をマスターしておくことで、セキュリティと柔軟性の両立が可能になります。
6. 開発者ツールを使ってCORS通信のリクエストとレスポンスを確認する方法
Spring BootでCORS設定を行ったあと、本当に正しく動作しているかどうかを確認するには、ブラウザの開発者ツールを使うのが便利です。ここではGoogle Chromeを例に、どのようにCORS通信を検証するかを初心者向けに丁寧に解説します。
まず、Chromeで対象のフロントエンドページ(たとえばhttp://localhost:3000)を開いた状態で、F12キーを押して開発者ツールを表示します。
次に、上部メニューから「Network(ネットワーク)」タブを選択し、CORS対象のリクエストを発生させる操作を行います。たとえばボタンをクリックしてバックエンドにアクセスするなどです。
リクエストが発生すると、一覧にAPIのURLが表示されるので、それをクリックして詳細を開きます。
- Headers(ヘッダー)タブを選択すると、「Request Headers」と「Response Headers」が表示されます。
- リクエストに
Originヘッダーが含まれているかを確認しましょう。 - レスポンスに
Access-Control-Allow-Originヘッダーが含まれていれば、CORSが許可されている証拠です。
また、開発者ツールの「Console(コンソール)」タブにも注目してください。ここにCORSエラーが赤字で表示される場合があります。設定ミスをした場合などは、このメッセージが重要なヒントになります。
「Spring Boot CORSエラー」が発生した場合、まずはこの開発者ツールでリクエストとレスポンスを確認し、必要なヘッダーが正しく含まれているかをチェックしましょう。
7. 本番環境でのCORS設定の注意点(セキュリティ対策)
開発環境では便利さを優先してaddAllowedOrigin("*")などを使ってしまいがちですが、本番環境ではセキュリティを意識したCORS設定が必須です。
まず絶対に避けるべきは、以下のような設定です。
config.addAllowedOrigin("*");
config.setAllowCredentials(true); // これは組み合わせNG
addAllowedOrigin("*")とsetAllowCredentials(true)の組み合わせは、セキュリティ上の問題があるため、ブラウザがブロックします。これは重大な設定ミスです。
本番環境では、信頼できるオリジンのみをaddAllowedOrigin("https://yourdomain.com")のように明示的に指定するようにしましょう。
また、不要なHTTPメソッドを許可しないこともセキュリティ対策になります。たとえばGETとPOSTしか使わないのであれば、次のように設定します。
config.setAllowedMethods(Arrays.asList("GET", "POST"));
さらに、HTTPヘッダーも最小限に限定することで、安全性を高めることができます。addAllowedHeader("*")ではなく、必要なヘッダーだけに絞るのが理想です。
Spring BootでのCORSセキュリティ対策は、システム全体の防御力を高めるための重要な要素です。たった一行の設定ミスで、予期しない外部アクセスを許可してしまうリスクがあるため、本番リリース前にはCORS設定を必ず見直す習慣をつけましょう。
8. CORSエラーが出たときのトラブルシューティング方法
最後に、「CORS トラブルシューティング」の観点から、よくあるエラーとその解決方法を紹介します。Spring BootアプリケーションでCORS設定をしても、フロントエンドからアクセスできない場合は、次のような点を確認してください。
8-1. エラー:No 'Access-Control-Allow-Origin' header is present
このエラーは、サーバーからのレスポンスにAccess-Control-Allow-Originヘッダーが含まれていない場合に発生します。設定が不足しているか、正しくマッピングされていない可能性があります。
グローバル設定を行った場合は、registerCorsConfiguration("/**", config)のように、正しくすべてのパスに適用されているかを確認してください。
8-2. エラー:The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*'...
このエラーは、先述の通りsetAllowCredentials(true)と*を組み合わせた場合に出ます。オリジンを*ではなく明示的に設定してください。
8-3. エラー:CORS preflight channel did not succeed
これは、プリフライトリクエスト(OPTIONSメソッド)が失敗したときに出るエラーです。多くの場合、OPTIONSリクエストに対してSpring Boot側が正しくレスポンスを返していないのが原因です。
Security設定やCORS設定で、OPTIONSメソッドも許可しているか確認しましょう。
8-4. 対処法のまとめ
- 開発者ツールでヘッダーをチェック
- ログ出力を確認(CORS拒否が出ていないか)
- オリジンの指定ミス(URLのtypoやポート番号違い)
- メソッドやヘッダー制限が原因でブロックされていないか
こうしたトラブルの原因は意外と基本的な見落としにあることが多いため、落ち着いてひとつずつ確認するのが解決の近道です。
「Spring Boot CORSエラー」に遭遇したら、今回紹介したチェックリストを参考に、順を追って原因を突き止めてください。
まとめ
Spring BootにおけるCORS設定の全体像を振り返る
ここまで、Spring BootでCORSを設定する方法について、基礎から実践、そして本番環境での注意点やトラブルシューティングまで段階的に解説してきました。CORSは「エラーが出たからとりあえず解除するもの」ではなく、Webアプリケーション全体の安全性を守るために欠かせない重要なセキュリティ機構です。特にフロントエンドとバックエンドを分離して開発する現代的な構成では、Spring BootとCORSの理解は避けて通れません。
CORSの本質は、ブラウザが持つ同一オリジンポリシーを前提に、「どのオリジンからのアクセスを許可するのか」をサーバー側が明示的に制御する点にあります。Spring Bootでは、@CrossOriginアノテーションを使ったコントローラ単位の設定、SecurityConfigでのグローバル設定、さらにはFilterを用いた柔軟な制御など、用途に応じた複数の選択肢が用意されています。
開発環境と本番環境で意識すべきCORS設計
開発中は利便性を優先してオリジンを広く許可してしまいがちですが、本番環境では「必要最小限」を強く意識する必要があります。特定のドメインだけを許可し、不要なHTTPメソッドやヘッダーを制限することで、意図しないアクセスや情報漏えいのリスクを下げることができます。Spring BootのCORS設定は一度書いたら終わりではなく、環境や仕様変更に応じて見直すことが大切です。
また、setAllowCredentials(true)とワイルドカード指定の組み合わせが使えない点など、仕様を正しく理解していないとハマりやすいポイントも多く存在します。CORSエラーが出たときは、焦らずにブラウザの開発者ツールでリクエストヘッダーとレスポンスヘッダーを確認し、Access-Control-Allow-OriginやOriginの値を一つずつ検証する姿勢が重要です。
サンプルプログラムで考えるCORS設定の考え方
以下は、これまでの内容を踏まえたシンプルなCORS設定例です。Spring BootとSpring Securityを組み合わせた場合の基本形として、理解の整理に役立ててください。
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf().disable();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("http://localhost:3000");
config.addAllowedMethod("GET");
config.addAllowedMethod("POST");
config.addAllowedHeader("Content-Type");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/api/**", config);
return source;
}
}
このように、URLパターン・許可するオリジン・HTTPメソッド・ヘッダーを明確に定義することで、Spring Bootアプリケーションの安全性と保守性は大きく向上します。単に動かすだけでなく、「なぜこの設定が必要なのか」を意識することが、実務で通用するスキルにつながります。
生徒:「CORSって、ただのエラー対処だと思っていましたけど、セキュリティの考え方そのものなんですね。」
先生:「その通り。Spring BootでCORSを設定する目的は、通信を許可することよりも、不要な通信をきちんと拒否することにあるんだよ。」
生徒:「@CrossOriginとSecurityConfig、どちらを使うかも状況次第なんですね。」
先生:「うん。小規模ならコントローラ単位、大規模ならグローバル設定やFilterが向いている。設計の視点を持つことが大切だね。」
生徒:「本番環境ではオリジンやメソッドを絞らないと危険なのも理解できました。」
先生:「それを意識できれば十分。Spring BootとCORSを正しく理解すれば、フロントエンドとバックエンドを安心して連携できるようになるよ。」