0
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?

【ネットワーク】CORS

Posted at

はじめに

こんにちは。アメリカに住みながら、独学でエンジニアを目指しているTairaです。

現在インターネットの知識の確認するインターネットクイズを定期的にやっているのですが、そこで出てきたCORSについて説明していきたいと思います

CORSの説明の前に

CORS(Cross-Origin Resource Sharing)を説明する前に、オリジンについて説明します。
オリジンは一般的に以下の3つを合わせたものを指します

  • スキーム (http/または https)
  • ドメイン名/IP (localhost, example.com など)
  • ポート番号 (3000, 5173 など)

これらの任意の1つが異なると、別オリジンとして取り扱われ、JavaScriptからのリクエストをブロックするという機能をブラウザが標準搭載しています(同一オリジンポリシー(SOP)の制限)。

なぜCORSが必要か

通常、ブラウザはセキュリティ上の理由から、異なるオリジン間での通信を制限しています(たとえば、example.com のページが api.example.net にアクセスすることは制限される)。
例えば以下のようなフロントとバックエンドを分けてAPIで接続するようなアプリを考えてみます。

この場合、ポートが違うのでオリジンが異なると見なされます。このとき、フロントエンドからAPIへアクセスすると、CORSエラーになります。

そこでCORSが役に立つ

それらのような、異なるオリジン(ドメイン、ポート、プロトコルが異なる)間でのリソースの共有を可能にする仕組みをCORSといいます。
ブラウザのセキュリティ機能の一部であり、**同一オリジンポリシー(SOP)**の制限を一部緩和するために使われます。

セキュリティ例:

ユーザーが https://mybank.com でログインしている時、別のWebサイト evil.com が JavaScriptを使って、勝手に mybank.com のAPIへ送金リクエストを投げるとします。

このような攻撃は current_user やセッションIDを使った障害行為を実行できるため、CORSのようなブラウザ側の防衛系統が必須なのです。

React と Rails を分離して開発する場合

React(フロントエンド): http://localhost:5173
Rails(APIバックエンド): http://localhost:3000

これらはポートが違うため、同じPCで動いているとしても別オリジンとして扱われます。
そのためCORSの設定をRails側で行う必要があります。

例: config/initializers/cors.rb

Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins 'http://localhost:5173'
    resource '*',
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head],
      credentials: true
  end
end

補足: CORSエラーのよくある原因と対応

1. フロントエンドのリクエストに credentials: 'include' が設定されていない

CORSでCookieやセッション情報をやり取りする場合、フロントエンド側でも以下のように credentials: 'include' を明示する必要があります。

fetch('http://localhost:3000/api/example', {
  method: 'GET',
  credentials: 'include'
})

2. credentials: true を設定しているのに origins '*' にしている

Rails側で credentials: true を設定する場合、オリジンをワイルドカード('*')にするとエラーになります。必ず具体的なオリジン(例:http://localhost:5173)を指定しましょう。

3. OPTIONSメソッドへの対応が不足している

ブラウザは "事前リクエスト(preflight)" として OPTIONS リクエストを送る場合があります。このため、Rails側で :options を明示的に許可しておく必要があります。

methods: [:get, :post, :put, :patch, :delete, :options, :head]

4. 本番環境でのドメイン指定忘れ

本番では localhost ではなく、本番のURL(例:https://myapp.com)を指定する必要があります。複数環境に対応するには、環境ごとに切り替えるように設定を工夫しましょう。

0
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
0
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?