@CrossOriginの使い方を完全ガイド!ControllerレベルでのCORS設定を初心者向けに解説
新人
「外部サイトから自分のSpringアプリにアクセスしようとすると、CORSエラーが出るんですけど…」
先輩
「それはCORS(コース)の設定がされていないからだね。@CrossOriginアノテーションを使うと解決できるよ。」
新人
「えっ、それってどこに書けばいいんですか?難しそう…」
先輩
「Controllerクラスに直接書くだけでCORS設定ができるから簡単だよ。順を追って説明するね!」
1. @CrossOriginとは何か?
@CrossOrigin(クロスオリジン)とは、Spring Frameworkで提供されているCORS(Cross-Origin Resource Sharing)設定用のアノテーションです。ブラウザのセキュリティ上、異なるオリジン(ドメイン)間でのリソースアクセスは制限されています。例えば、http://example.com から http://localhost:8080 のAPIにアクセスしようとすると、ブラウザが「CORSポリシー違反」としてブロックします。
このとき、SpringのControllerに@CrossOriginアノテーションをつけてCORS設定をしておくことで、外部からのアクセスを許可できるようになります。
例えば以下のように書きます。
@Controller
public class SampleController {
@CrossOrigin(origins = "http://example.com")
@GetMapping("/data")
public String getData(Model model) {
model.addAttribute("message", "データを取得しました");
return "dataView";
}
}
このように書くと、http://example.com からこのAPI(/data)にアクセスする際、CORSエラーが発生しなくなります。
2. なぜControllerレベルでCORS設定ができるのか
Springでは、CORS設定をグローバルにも、クラスやメソッド単位のControllerレベルにも設定できます。Controllerレベルでの設定は、Springがリクエストを処理する仕組みの一部に統合されているため可能なのです。
Spring MVCは、各リクエストをハンドリングする前に、リクエストヘッダーをチェックし、CORS設定があればそれに応じてレスポンスヘッダーを追加します。つまり、Controllerのメソッドに@CrossOriginをつけると、そのメソッドに対するアクセス時だけ、CORS設定が有効になります。
以下は、複数のオリジンからのアクセスを許可する例です。
@Controller
@RequestMapping("/api")
public class ApiController {
@CrossOrigin(origins = {"http://example.com", "http://another.com"})
@PostMapping("/submit")
public String submitData(@RequestParam String name, Model model) {
model.addAttribute("name", name);
return "resultView";
}
}
このようにControllerレベルでCORSを設定することで、細かくアクセス制御を行うことができ、「一部のAPIだけ外部に公開したい」という要件にも対応できます。
さらに、許可するHTTPメソッドやヘッダーなども柔軟に設定可能です。
@CrossOrigin(
origins = "http://frontend.com",
methods = {RequestMethod.GET, RequestMethod.POST},
allowedHeaders = "*"
)
このような詳細設定により、CORSのセキュリティと利便性を両立できます。
Spring Securityとの関係にも注意しよう
Spring Securityを導入している場合、@CrossOriginだけではCORS設定が反映されないことがあります。これはSpring Securityが独自にリクエストの前処理をしているためで、セキュリティ側にもCORSの許可設定を行う必要があるからです。
以下は、Spring Security側でもCORSを許可する設定例です(WebSecurityConfigurerAdapterは非推奨になっているためJava Configで設定)。
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors(Customizer.withDefaults())
.authorizeHttpRequests(authorize -> authorize
.anyRequest().permitAll()
);
return http.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("http://frontend.com");
config.addAllowedMethod("*");
config.addAllowedHeader("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
}
このように、Controllerレベルの@CrossOriginと、Spring SecurityでのCorsConfigurationSourceの両方を適切に設定することで、CORS 設定が完全に機能します。
3. @CrossOriginを使った基本的な使い方(シンプルな例)
それでは、実際にControllerクラスで@CrossOriginアノテーションを使って、基本的なCORS 設定をしてみましょう。ここではもっともシンプルな書き方を紹介します。
以下は、特定のドメイン(例:http://localhost:3000)からのアクセスを許可する例です。Reactなどのフロントエンドアプリから、Springのバックエンドにアクセスするケースでよく使います。
@Controller
public class HelloController {
@CrossOrigin(origins = "http://localhost:3000")
@GetMapping("/hello")
public String hello(Model model) {
model.addAttribute("greeting", "こんにちは");
return "helloView";
}
}
このようにControllerのメソッドに@CrossOriginをつけるだけで、そのメソッドに対するCORS 設定が反映されます。特に初学者の方にとっては、設定が直感的でわかりやすく、学習しやすいのがメリットです。
また、originsをワイルドカード("*")にすると、すべてのオリジンを許可することもできますが、本番環境ではセキュリティ上おすすめできません。
4. メソッドごとのCORS設定とクラス全体への適用の違い
@CrossOriginは、メソッド単位でもクラス単位でも記述可能です。どちらを使うかは、どの範囲でCORS設定を有効にしたいかによって使い分けます。
メソッドごとに設定すると、必要なエンドポイントだけCORSを許可できます。以下の例では、/api/oneだけにCORS 設定が適用されています。
@Controller
@RequestMapping("/api")
public class PartialCorsController {
@CrossOrigin(origins = "http://frontend.local")
@GetMapping("/one")
public String methodOne(Model model) {
model.addAttribute("msg", "メソッド1");
return "viewOne";
}
@GetMapping("/two")
public String methodTwo(Model model) {
model.addAttribute("msg", "メソッド2");
return "viewTwo";
}
}
この場合、/api/oneはCORSが許可されますが、/api/twoは許可されません。
一方、クラスの先頭に@CrossOriginをつけると、すべてのメソッドにCORS設定が適用されます。次の例を見てください。
@Controller
@CrossOrigin(origins = "http://frontend.local")
@RequestMapping("/all")
public class AllCorsController {
@GetMapping("/a")
public String a(Model model) {
model.addAttribute("data", "A");
return "viewA";
}
@PostMapping("/b")
public String b(Model model) {
model.addAttribute("data", "B");
return "viewB";
}
}
このようにクラスに対して@CrossOriginを指定すれば、同じ設定がすべてのメソッドに適用されるため、コードの重複が減ります。特定のドメインからのリクエストを広範囲に許可したい場合に便利です。
ただし、APIの公開範囲に応じて柔軟に設定するためには、メソッドごとの指定も重要になる場面があります。
5. 他のCORS設定方法(WebMvcConfigurerなど)との使い分け方
@CrossOriginはControllerレベルで手軽に設定できる反面、大規模なシステムや複雑な条件分岐にはやや不向きです。そんなときに使えるのが、WebMvcConfigurerインターフェースを使ったCORS 設定です。
例えば以下のように設定します。
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://frontend.local")
.allowedMethods("GET", "POST")
.allowedHeaders("*");
}
}
この方法では、特定のパスパターン(/api/**など)に対してCORSを一括で設定できます。Controllerに直接アノテーションを書かなくてもよいので、コードの見通しが良くなります。
では、どちらを使えばよいのでしょうか?以下のように使い分けるとよいでしょう。
Controllerレベル(@CrossOrigin)がおすすめなケース
- テストや学習目的で一部のAPIだけにCORSを許可したいとき
- Controller単位でCORSポリシーを柔軟に切り替えたいとき
- クラスやメソッドにわかりやすく明示したいとき
WebMvcConfigurerがおすすめなケース
- API全体に共通ルールでCORS設定を適用したいとき
- 環境やパスパターンによって設定を切り替えたいとき
- 複数プロジェクトで再利用しやすい構成にしたいとき
どちらの方法でも、最終的には正しくCORS 設定が行われていれば、外部オリジンからのアクセスは許可されます。ただし、@CrossOriginは初心者にも使いやすく、特にSpring Securityと組み合わせて動作させるときに理解しやすいため、まずはこちらから試してみるのが良いでしょう。
開発環境がpleiadesであっても、Gradleを使っている場合は依存関係の管理も簡単なので、設定のテストや切り替えも容易に行えます。Controller CORSの設定を理解する第一歩として、@CrossOriginの基本を押さえておきましょう。
6. @CrossOriginを使用する際の注意点(セキュリティの観点)
@CrossOriginアノテーションはとても便利ですが、使い方を誤るとセキュリティ上のリスクが発生します。初心者の方にもよくあるのが、origins = "*" を指定して、すべてのオリジンからのアクセスを許可してしまうケースです。
この設定は開発中のテストには便利ですが、本番環境では極力避けるべきです。理由は、不正なオリジンからのアクセスまで許可してしまう可能性があるからです。APIが重要なデータを扱っている場合、クロスサイトスクリプティングや悪意ある攻撃にさらされるリスクが高まります。
実際の開発では、アクセスを許可するドメインを明示的に限定することが推奨されます。以下のように記述すると安全です。
@CrossOrigin(origins = "https://trusted-frontend.com")
また、HTTPメソッド(GETやPOSTなど)やヘッダーの制限も忘れずに行うと、セキュリティが強化されます。
@CrossOrigin(
origins = "https://trusted-frontend.com",
methods = {RequestMethod.GET},
allowedHeaders = {"Content-Type"}
)
このように、Spring Securityと連携する前提で@CrossOriginによるCORS 設定を行うときは、常に「どこまで許可するのか」を意識することが大切です。特にControllerレベルでのCORS設定は細かい制御ができる反面、適切なポリシー設計が求められます。
7. 設定が反映されないときの原因と対処法
せっかく@CrossOriginでCORS設定をしても、ブラウザ上でCORSエラーが出続けてしまうことがあります。これは初心者にとって非常に混乱しやすいポイントです。以下に、よくある原因とその対処法をまとめました。
① Spring SecurityがCORSをブロックしている
Spring Securityを導入していると、@CrossOriginの設定が単体では効かないことがあります。これはセキュリティフィルターがCORSリクエストを処理する前にリクエストをブロックしてしまうからです。
この場合は、SecurityConfigクラスでcors()とCorsConfigurationSourceの設定を追加しましょう(前述済)。
② OPTIONSリクエストへの対応が不足している
ブラウザはCORSリクエストを送信する前に、「プリフライトリクエスト」としてOPTIONSメソッドで事前確認を行います。このとき、Springの設定でOPTIONSを許可していないと、リクエストが失敗します。
対応方法としては、ControllerでOPTIONSメソッドを明示的に許可するか、@CrossOriginのmethodsにRequestMethod.OPTIONSを追加します。
@CrossOrigin(
origins = "https://frontend.local",
methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.OPTIONS}
)
③ ブラウザのキャッシュやHTTPS設定
一度CORSエラーが発生すると、ブラウザがその情報をキャッシュして、あとから設定を直しても反映されない場合があります。キャッシュのクリアやシークレットモードでの再確認を行いましょう。
また、HTTPS環境とHTTP環境が混在していると、ブラウザ側がブロックすることもあります。同じプロトコルで統一することも重要です。
8. @CrossOriginのCORS設定を確認する方法(ブラウザとログでチェック)
実際に@CrossOriginでCORS設定を行ったあと、正しく設定が反映されているか確認することが大切です。ここではブラウザとログを使ったチェック方法を紹介します。
ブラウザの開発者ツールで確認する
Google ChromeやFirefoxなどのブラウザでは、「開発者ツール(F12)」を開き、[ネットワーク]タブでCORS関連のリクエストを確認できます。
リクエストを選択して、「レスポンスヘッダー」に Access-Control-Allow-Origin が設定されているかをチェックしましょう。以下のように表示されていれば、CORS設定は正しく反映されています。
Access-Control-Allow-Origin: https://frontend.local
逆に、このヘッダーが表示されていない、もしくは「null」になっている場合は、CORS 設定に何か問題があるというサインです。
Springのログを活用する
開発環境がpleiades + Gradleで構築されている場合、IDE内のコンソールに出力されるログも確認ポイントになります。CORSの設定が有効になると、SpringのログにCORSリクエストの情報が表示されることがあります。
もしログにCORS関連の処理が一切表示されていなければ、Controllerに@CrossOriginの記述漏れがないか、CORS設定用のBeanが正しく読み込まれているかをチェックしましょう。
curlコマンドで確認する
ブラウザ以外にも、curlコマンドでCORSレスポンスを確認することができます。
curl -i -X GET http://localhost:8080/hello -H "Origin: https://frontend.local"
この結果にAccess-Control-Allow-Originヘッダーが含まれていれば成功です。ログと合わせて確認することで、ControllerレベルでのCORS設定の動作確認ができます。
このように、設定だけでなく確認作業も丁寧に行うことで、CORSのトラブルを未然に防ぐことができます。@CrossOriginによるController CORS 設定は便利な反面、セキュリティやブラウザの挙動に左右される部分もあるため、検証を欠かさないことが大切です。