【初心者向け】CORSについて理解しよう!

WEB

APIを実装するとなったときにCORS(オリジン間リソース共有)というワードに出会い、「CORSって何だ?」と思ったのでまとめます。(恥かしいことながらこのとき初めて知りました)

この記事で書いてあること

・ざっくりHTTP通信とは
・同一オリジンポリシーとは
・CORSが何かを理解する
・LaravelでのCORS設定方法

まずCORSの話に入る前に、前提としてHTTP通信とは何かということをざっくり説明します。

そんなの知ってるよという方は読み飛ばしてください。

HTTPとは通信プロトコルの1つです。

プロトコルとは2者間で通信をするときに「こういう感じでやり取りしましょう」といったお決まりごとみたいなものですね。

HTTP以外にもよく聞くところだと、「SMTP」、「TCP/IP」、「FTP」など様々なプロトコルが存在します。

ではHTTPはどういった通信をしているかと言うと、

クライアント(ブラウザ等)はサーバーに対して「このページが見たい」というリクエストを要求します。

その要求に対してサーバーが「こちらがそのページです」とレスポンスを返します。

図で表すとこんな感じです。

普段は何も意識せずウェブページを見ているかと思いますが、こういうやり取りが高速で行われています。

HTTPについてはもっと説明すべきことがあるのですが、今回は本題ではないのでこの辺にしておきます。

もっと知りたいという方は下記を参考にしてください。

HTTP の概要 - HTTP | MDN
HTTP は、 HTML 文書などのリソースを読み取るためのプロトコルです。 これはウェブにおけるデータ交換の基礎をなし、クライアントサーバープロトコルであり、リクエストは受け取り者(一般にはウェブブラウザー)が生成します。 文書全体は、テキスト、レイアウトの定義、画像、動画、スクリプトなど、取り込まれたさまざ...

CORSの概要

先にCORSとは何なのか簡単に説明します。

同一オリジンポリシーの元、異なるオリジンからのリソースへのアクセスは制限されていますが、異なるオリジンからのリクエストでもアクセスできるようにした仕組みです。

聞き慣れないワードもあると思いますのでそれぞれ解説していきます。

オリジンとは

まずオリジンとは下記のことを指します。

スキーム(プロトコル) + ドメイン(ホスト) + ポート

例)http + example.com + 80

同一オリジンと異なるオリジンの違いを見ていきましょう。

http://r-tech14.com/example1
http://r-tech14.com/example2

スキームとドメインが同じなので同一オリジン

http://r-tech14.com:80
http://r-tech14.com

既定で80番ポートはHTTPコンテンツを配信するため同一オリジン


http://r-tech14.com/example1
https://r-tech14.com/example2

スキームが異なるため同一オリジンではない

http://www.r-tech14.com
http://api.r-tech14.com

サブドメインが含まれるとドメインが異なるため同一オリジンではない

http://r-tech14.com
http://r-tech14.com:8080

ポートが異なるため同一オリジンではない

同一オリジンポリシー

異なるオリジンからのリソースへのアクセスを制限するウェブのセキュリティにおける重要な仕組みです。

他のオリジンからのアクセスを何でも許可していると、悪意あるユーザーがスクリプトを埋め込んだりしてリソースに対して攻撃されてしまいます。

同一オリジンポリシーによって安全性はもたらされることはメリットですが、デメリットも存在します。

柔軟性に乏しい点ですね。

Web開発を行うにあたり、異なるオリジンにあるリソースへアクセスしたいケースもあるかと思います。

例えば、Webサービスがサブドメインごとにコンテンツが分かれていて、別のサブドメインのコンテンツにアクセスしたいケースなどです。

こういったことを解決するためにCORSを設定してクロスオリジンからのアクセスも許可してあげるようにします。

CORS機能概要

CORSを設定してあげることでブラウザから情報を読み取ることが許可されているオリジンをサーバー側で指定することできます。

CORSという文脈ではリクエストの種類に単純リクエストプリフライトリクエストの2つが存在します。

単純リクエスト

以下のすべての条件を満たすものです。

  • GET、POST、HEADメソッドのうちの1つであること
  • 設定できるヘッダーはAccept、Accept-Language、Content-Language、Content-Type
  • Content-Typeヘッダーがapplication/x-www-form-urlencoded、multipart/form-data、text/plain のいずれかに設定されている場合

一方でプリフライトリクエストは単純リクエストではない場合に送信されます。

プリフライトリクエスト

OPTIONSメソッドによるリクエストを他のドメインにあるリソースに向けて送り、実際のリクエストを送信しても安全かどうかを確かめます。

プリフライトリクエストが許可されると実際のリクエストが送信されます。

逆に許可されないと実際のリクエストはブロックされます。

CORS設定してないオリジンからのリクエスト

CORS設定しているオリジンからのリクエスト

クライアント側からクロスオリジンへのリクエストの際はOriginヘッダーが自動で付与されます。

サーバー側はOriginヘッダーのオリジンがCORSに設定されているかを確認し、CORSに設定されていればAccess-Control-Allow-Originというレスポンスヘッダーを返します。

しかし、Access-Control-Allow-Origin: *と設定されていると、リソースに対してすべてのドメインからアクセスできることを意味します。

これではCORSを設定している意味がないので、Access-Control-Allow-Origin: http://r-tech14.comと返してあげることでhttp://r-tech14.com以外からのアクセスを制限します。

LaravelでのCORS設定

最後にLaravelではどのように設定するのかを解説します。

laravel-corsというライブラリが存在し、簡単に設定することが可能です。

Laravel7.*以降であればデフォルトでサポートされています。

設定ファイルはconfig/cors.phpです。

デフォルトではガバガバの状態なので利用する際はしっかりアクセス制限できるようにそれぞれの項目を指定していきます。

pathsAccess-Control-Expose-Headersを設定するパス 例: ['api/*']
allowed_origins許可するリクエストオリジンの設定 例: *.mydomain.com
allowed_origins_patterns許可するリクエストオリジンを正規表現を使用して設定します
allowed_methods許可するリクエストメソッド
allowed_headersAccess-Control-Allow-Headersの表示
exposed_headersAccess-Control-Expose-Headersの表示
max_ageAccess-Control-Max-Ageの値
supports_credentialsAccess-Control-Allow-Credentialsの表示

仕事でCORSのエラーにハマり、その時CORSって何だ?ってなったのでこれを気にまとめてみました。

まだまだウェブの世界は知らないことが多いので学び続けます。

最後までご覧いただきありがとうございます。

コメント

タイトルとURLをコピーしました