LoginSignup
7
4

More than 1 year has passed since last update.

「APIを叩いてもCORSで弾かれた」の対応はこれ

Last updated at Posted at 2021-12-20

はじめに

開発環境にデプロイする際にセキュリティの観点から「APIを叩いてもCORSで弾かれた」ため、それに伴うアウトプットをします。
※個人ブログから技術的アウトプットはQiitaへ引っ越ししたので、こちらは過去に書いたブログとなります。

エラーの事象

開発環境にデプロイする際にセキュリティの観点から
APIを叩いてもCORSで弾かれた 」です。

背景

まず冒頭の

開発環境にデプロイする際に

ということですが、今までローカル環境では、nuxt.config.jsの設定でproxyサーバーを立てることができていたので、サーバー側でCORS対応をする必要ありませんでした。

しかし、Firebaseのhostingにデプロイした際にproxyサーバーを立てることができずに、結果、冒頭に書いたAPIを叩いてもCORSで弾かれました。  

調べてみると、セキュリティの観点から、オリジン(HTMLが置かれたサーバー)以外のサーバーからデータを取得すること(=CORS:Cross-Origin-Resource-Sharing)を、現在のブラウザでは許可していないようです。

こちらを回避するためには、サーバー側にて、CORSを許可する必要とのこと。

CORSとは

そもそもCORS、CORSと書いてるが、CORSとはなにか?
僕は先日始めてこの英単語の組み合わせ達に鉢合わせました。

  • 読み方: コルス
  • Cross-Origin Resource Sharing の略
  • 訳すと「 オリジン間リソース共有

ではこのオリジンとはなにか??

  • オリジンは ドメイン と似た概念似てるようで全く異なる概念
  • ドメイン(例):google.com
  • オリジン(例):https://www.google.com:443
  • つまり、ドメインとの 見た目上の違い はプロトコルとホストとポート番号を含んでいるという点

オリジン == プロトコル + ホスト + ドメイン + ポートナンバー

※ URLを構成する要素を整理について
※ クエリストロングではなく、 クエリストリング(文字列) です....笑  何を強くしてるねん....

URLを構成する要素を整理についてはこのツイートがわかりやすい

※ クエリストロングではなく、 クエリストリング(文字列)だと思われる


 

オリジンを踏まえた上でCORSとは?

  • CORS は日本語訳すると オリジン間リソース共有 (上述)。

  • つまり CORS とは、あるオリジンで動いている Web アプリケーションに対して、別のオリジンのサーバーへのアクセスをオリジン間 HTTP リクエストによって許可できる仕組みのことをいう

  • 許可できるようになるまでの仕組みとしては、サーバーからのレスポンスにリソースの共有を許可するための特別なヘッダーを追加して動作できるようになる
    image.png

なぜCORSが必要なのか?

これは上述のように、昨今のブラウザでは、フロントエンドJavaScriptから違うドメインへのアクセスに対して、CORSがサーバ側で許可されている場合を除き、セキュリティ上の問題からアクセスをしない仕様となっているため。

どんな時にクロスオリジンにアクセスするか?

基本的には、

  • XML HttpRequest(Ajax)
  • FetchAPIでの非同期通信する時

などって思ってOK

CORSのリクエストの種類

XMLHttpRequestを用いてオリジン間リソース共有がどのように動作するかを説明

リクエストによっては CORSを引き起こさないものがあるみたい。

そこでリクエストを2つ(単純リクエストとプリフライト リクエスト)に分けます。

▼ 単純リクエスト

上述通り、CORSを引き起こさないもの。

例えば以下のメソッド

  • GET
  • POST
  • HEAD

image.png

▼プリフライト リクエスト

単純リクエストとは異なり、リクエストの始めに OPTIONSメソッド で対象の異なるオリジンにリクエストを送り、実際のリクエストを送っても問題ないか確認するリクエストをプリフライト リクエストという

該当するリクエストは以下

  • PUT
  • DELETE
  • CONNECT
  • OPTIONS
  • TRACE
  • PATCH 

HTTPのOPTIONSメソッドとは

  • HTTPで使われるメソッドといえば、上記のようなGETやPOSTが一般。
  • 一方、OPTIONSメソッドは、これらのメソッドのうち、サーバーがどのメソッドをサポートしているかを調査するためのメソッド。
  • どこで使われるのかと言うと、ブラウザがCORSを検出した場合、実際のメインメソッド(GETやPOST)を投げる前に、OPTIONSメソッドによる検査を実行するような仕様になっています。そしてプリフライトリクエストを投げて、そこからOKであれば、204でレスポンスが返ってきて、そこからメインリクエスト(GETメソッド)が返ってくる。つまりレスポンスが2個返ってくる!(下図)

image.png

つまり、APIサーバの実装には

  1. CORSを有効にする(HTTPレスポンスヘッダにAccess-Control-Allow-Origin等の実装)に加え、
  2. OPTIONSメソッドの実装

が必要ということ

express で CORS を許可する

今回は、CORS とはなにか?が中心だったので、最後にかんたんにコードで説明します。

CORSを許可するための実装には、

  • XHR を使う場合
  • Fetchを使う場合
  • axios を使う場合
  • Expressを使う場合

などがあり、開発推進課ではNodeのExpressを使っているので、それを使ってCORS を許可する。

▼cors モジュールをimport 

Node.js
import cors from 'cors';
app.use(cors());

ちなみに

Node.js
app.use(cors());

 だと フルで CORS 周りの設定を許可していることになるみたいです。

また、特定の API に対して個別にCORSを許可する場合は、以下のように

Node.js
api.use(cors(corsOptions));

で指定できます。

例えば、ローカルホストや開発環境だったら、どこからでも叩けるようにして、それ以外はCORSで弾くみたいな感じの条件分岐で記述していく感じ。

まとめ

  • ブラウザでは、フロントエンドから違うドメインへのアクセスに対して、CORSがサーバ側で許可されている場合を除き、セキュリティ上の問題からアクセスできない場合が多い
  • このアクセスを許可するために、CORSを使う
  • CORSとは、「あるオリジンで動いている Web アプリに対して、別のオリジンのサーバーへのアクセスをオリジン間 HTTP リクエストによって許可できる仕組み、ルール」のこと
  • 許可するためには、CORSを有効にする(HTTPレスポンスヘッダーにAccess-Control-Allow-Origin等の実装)に加え、OPTIONSメソッドの実装する必要がある
  • HTTPで使われるメソッドといえば、GETPOSTが一般だが、一方、OPTIONSメソッドは「サーバーがどのメソッドをサポートしているかを調査するためのメソッド」。
  • プリフライトリクエストを投げて、そこからOKであれば、204でレスポンスが返ってきて、そこからメインリクエスト(GETメソッド等)200レスポンスが返ってくる。つまりレスポンスが204と200の2個返ってくる
  • CORSを許可するための実装には、XHRfetchaxiosExpressを使う場合などがある

疑問

  • Qiitaに書きながら思っていた謎
    • 謎1:GETメソッドでもCORSで弾かれてた点
      • → 調べてみると、GETメソッドでも弾かれるケースがあり、どうやら制限が厳しくなっているっぽい
    • 謎2:OPTONSメソッドとヘッダーを加えないといけないが、GERAのソースにはOPTONSメソッドしか書いていなかくても正しくAPIが返ってきている点
      • → どちらかだけ書いてればOKになったみたい(ここは制限がゆるくなった?)

参考

- オリジン間リソース共有 (CORS) - HTTP | MDN
- なんとなく CORS がわかる...はもう終わりにする。

7
4
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
7
4