CORSとは?クロスオリジンリクエストの基本を初心者向けにわかりやすく解説!
新人
「先輩!Webアプリを作ってたら、'CORS policyによりリクエストがブロックされました'ってエラーが出たんですが、これって何ですか?」
先輩
「ああ、それはCORS、つまりクロスオリジンリクエストに関する制限に引っかかってるんだ。よくある問題だね。」
新人
「クロスオリジンって、どういう意味なんですか?」
先輩
「簡単に言えば、別のサーバーやポート、ドメインからのリクエストを送るときのことだよ。じゃあCORSの基本から説明していくね。」
1. CORSとは?(基本概念の説明)
CORSとは?という言葉は「Cross-Origin Resource Sharing(クロスオリジンリソースシェアリング)」の略で、クロスオリジン通信を許可するための仕組みです。セキュリティ対策の一環として、ブラウザは同一オリジンポリシーという制限を設けています。
同一オリジンポリシーとは、同じドメイン・ポート・プロトコルでなければ、リソースへのアクセスを許可しないというルールです。例えば、以下のようなケースではオリジンが異なるとみなされます:
http://localhost:8080からhttp://localhost:8081にアクセスhttp://example.comからhttps://example.comにアクセスhttps://app.example.comからhttps://api.example.comにアクセス
これらのケースでは、JavaScriptでAPIを呼び出すときにエラーが発生することがあります。このとき必要なのが、CORSの設定です。
サーバー側で「このオリジンからのリクエストを許可しますよ」と明示的に伝えることで、ブラウザがブロックを解除してくれます。
このように、「CORSとは何か」を理解することで、Web開発のトラブルを避けることができるのです。
2. なぜCORSが必要なのか(セキュリティ上の背景)
そもそもなぜクロスオリジンリクエストを制限する必要があるのでしょうか?それは、悪意あるWebサイトからのリクエストを防ぐためです。
例えば、ユーザーがログインしている状態で、別の悪意あるWebページを開いたとします。そのページがユーザーの認証情報を使ってAPIにアクセスしようとしたら……とても危険です。
このような攻撃を防ぐため、ブラウザは自動的にクロスオリジン通信をブロックします。そして、「本当にその通信を許可していいのか」をサーバー側に確認するように求めます。
サーバー側で明示的に許可を出さなければ、ブラウザは通信を拒否します。この機能がまさにCORSの仕組みなのです。
具体的には、HTTPレスポンスに以下のようなヘッダーが必要になります:
Access-Control-Allow-Origin: http://localhost:3000
このようにして、どのオリジンからの通信を許可するかをサーバー側で制御することで、セキュリティを守ることができます。
一方で、設定を間違えると脆弱性の原因になるので注意が必要です。例えば、「*(すべて許可)」のように設定すると、意図しない第三者からのアクセスまで許可してしまう可能性があります。
そのため、「CORSのセキュリティ設定は慎重に行う」という意識が大切です。
3. CORSによるブロックの例(よくあるエラーのパターン)
実際のWeb開発でよく見かけるのが、「CORS policyによりリクエストがブロックされました」というエラーメッセージです。このメッセージは、ブラウザがサーバーからCORSの許可を受け取れなかった場合に表示されます。
たとえば、http://localhost:3000のReactアプリからhttp://localhost:8080のSpringアプリへリクエストを送る場合、オリジンが異なるため、CORSが適用されます。
サーバー側に適切なCORS設定がない場合、以下のようなエラーがブラウザの開発者ツールに表示されます:
Access to fetch at 'http://localhost:8080/api/data' from origin 'http://localhost:3000'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present
on the requested resource.
このようなエラーが出た場合は、CORSの設定漏れや、許可するオリジンのミスマッチが原因であることが多いです。
また、プリフライトリクエストが必要な場合には、OPTIONSメソッドの対応がサーバー側に実装されていないと同様にブロックされます。これも初心者がつまずきやすいポイントのひとつです。
4. ブラウザがブロックする理由とその仕組み
ここで、なぜブラウザがCORS制限を行うのか、その仕組みをもう少し詳しく見てみましょう。
ブラウザは、JavaScriptを通じて外部サイトにアクセスできる機能を持っています。しかしこれが自由すぎると、セキュリティ上のリスクが発生します。
そこで、ブラウザは同一オリジンポリシーという原則を設け、異なるオリジンからの通信に制限をかけているのです。
このとき、リクエストの種類に応じて、ブラウザは以下のどちらかの動作をします:
- シンプルリクエスト:特定の条件を満たすGETやPOSTなどは、そのままリクエストされる
- プリフライトリクエスト:条件を満たさない場合、事前に
OPTIONSメソッドでサーバーに確認
このプリフライトリクエストでは、サーバーが「このオリジンは許可されています」というレスポンスを返す必要があります。たとえば以下のようなヘッダーを返すことで、ブラウザに許可を伝えます:
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type
これらのヘッダーが含まれていない場合、ブラウザは本リクエストをキャンセルし、エラーを表示します。
つまり、Spring側がCORSを許可する明確なレスポンスを返すことが必要になるのです。
5. Java側(Spring)でのCORS許可設定の基本コード
では、SpringアプリケーションでCORSを許可する基本的な方法について解説します。CORSの設定は、コントローラ単位でも、全体的なグローバル設定としても行うことができます。
まずは、コントローラに直接CORS設定を記述する方法から見てみましょう。
@Controller
@RequestMapping("/api")
public class SampleController {
@CrossOrigin(origins = "http://localhost:3000")
@GetMapping("/data")
public String getData(Model model) {
model.addAttribute("message", "データ取得成功!");
return "data";
}
}
このコードでは、@CrossOriginアノテーションを使って、特定のオリジンからのアクセスだけを許可しています。これにより、「CORS エラー 対処」のひとつとして、簡単に設定できます。
次に、アプリケーション全体に適用したい場合は、WebMvcConfigurerを使った設定方法があります。
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("GET", "POST", "OPTIONS")
.allowedHeaders("*");
}
}
この方法は、全てのAPIに一括してCORSを適用したい場合に便利です。また、開発中だけ許可するようにして、本番環境ではオリジンを限定することが推奨されます。
このようにSpringでは、非常に柔軟にCORSの設定が可能です。「Spring CORS設定」というキーワードで検索しても、これらの方法が多く紹介されています。
初心者の方は、まず@CrossOriginを使って小さく設定し、後からグローバル設定へ移行していくと理解しやすいでしょう。
6. よくあるCORS設定ミスとその対処方法
CORSの設定では、ちょっとしたミスが思わぬエラーを招くことがあります。初心者がつまずきやすいポイントを押さえておくことで、「CORS設定 ミス」によるトラブルを未然に防ぐことができます。
まずありがちなのが、オリジン指定の誤りです。たとえばhttp://localhost:3000とhttp://localhost:3000/(末尾のスラッシュあり)は別オリジンとして扱われます。このようなわずかな違いでも、Spring側では正しく認識されないことがあります。
また、プリフライトリクエストに対する対応漏れも多いです。JavaScript側でContent-Type: application/jsonを指定していると、ブラウザはOPTIONSメソッドで事前確認を行います。Spring側でこのリクエストに対して許可ヘッダーを返さないと、通信がブロックされます。
さらに、グローバル設定とアノテーションの併用による競合にも注意が必要です。設定が重複した場合、意図しない挙動になることがあります。開発段階ではどちらか一方に統一しましょう。
最後に、CORS設定の変更を行ったあとは、ブラウザのキャッシュやプリフライト結果が影響している場合もあるため、開発者ツールでキャッシュをクリアして再確認することも重要です。
7. @ControllerでのCORS制御方法(個別のエンドポイントで許可)
Springでは、@Controllerを使って個別にCORS制御ができます。これにより、特定のエンドポイントだけを明示的に許可することができ、セキュリティも保ちやすくなります。
以下は、@Controllerクラスの中で、@CrossOriginアノテーションを使って個別のメソッドに対してCORSを許可するサンプルです:
@Controller
@RequestMapping("/user")
public class UserController {
@CrossOrigin(origins = "http://localhost:3000")
@PostMapping("/create")
public String createUser(@RequestParam String name, Model model) {
model.addAttribute("result", name + "さんを作成しました");
return "userResult";
}
@GetMapping("/info")
public String getUserInfo(Model model) {
model.addAttribute("info", "ユーザー情報を取得しました");
return "userInfo";
}
}
このようにすると、/user/createはCORSを許可し、/user/infoは許可しないという細かい制御が可能です。「CORS Spring セキュリティ」という観点からも、すべてを一括許可するより安全です。
また、必要に応じてallowedMethodsやallowedHeadersなどを個別に指定することで、さらに厳密な制御が可能になります。
ただし、この方法は設定が増えるとメンテナンスが大変になるため、複数のエンドポイントがある場合はグローバル設定と併用する方が効率的です。
8. CORS設定のベストプラクティスとセキュリティ上の注意点
最後に、CORS設定を行ううえでのベストプラクティスとセキュリティの観点からの注意点について紹介します。
まず大前提として、許可するオリジンは必要最小限に限定することが重要です。*(すべてのオリジンを許可)を安易に使うと、意図しない第三者からのアクセスまで許可してしまい、セキュリティリスクになります。
また、開発環境と本番環境で設定を分けることも基本です。開発中はlocalhostを許可し、本番ではhttps://app.example.comのような本番ドメインだけを指定するようにしましょう。
さらに、認証情報を含めた通信(Cookieやトークン)を行う場合には、allowCredentials(true)と、オリジンの明示的指定を組み合わせる必要があります。*とallowCredentialsは併用できないため注意が必要です。
以下は、セキュリティを考慮したグローバルCORS設定の例です:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("https://app.example.com")
.allowedMethods("GET", "POST")
.allowCredentials(true)
.allowedHeaders("Content-Type", "Authorization");
}
}
このように、オリジンを明示し、許可するメソッド・ヘッダーも制限することで、より堅牢なCORS設定になります。
また、CORSのエラーは「設定が正しくない」と決めつける前に、フロントエンド側のリクエスト形式やヘッダーの設定も確認しましょう。意図せずプリフライトが発生しているケースも多く、バックエンドだけで解決できない場合もあります。
初心者のうちは、少しずつ確認・検証しながら設定を進めることがトラブル回避の近道です。しっかり理解を深めて、「CORS Spring セキュリティ」を意識した安全な設計を心がけましょう。