ExpressでのCORSの処理

CORSを設定してクロスサイトリクエストを許可する方法

ブラウザで実行されているJavaScriptアプリケーションは、通常、それらを提供する同じドメイン(オリジン)からのHTTPリソースにのみアクセスできます。

同じオリジンからの画像またはスクリプト/スタイルのロードは常に機能します。また、を使用してWebフォントをロードする@font-faceデフォルトで「同一生成元」ポリシーが設定されています。他のあまり人気のないもの(WebGLテクスチャやdrawImageCanvas APIにロードされたリソース)。

ただし、外部のサードパーティサーバーへのXHRおよびFetch呼び出しは失敗します。これは、サードパーティのサーバーが接続を確立し、要求されたリソースをダウンロードして使用できるようにするメカニズムを実装していない限りです。

このメカニズムはCORSクロスオリジンリソースシェアリング

CORSが必要な非常に重要なことの1つは、ESモジュール、最近、最新のブラウザに導入されました。

CORSポリシーを設定しない場合サーバー上サードパーティのオリジンにサービスを提供できるようにすると、リクエストは失敗します。

フェッチ例:

Fetch failed because of CORS policy

XHRの例:

XHR request failed because of CORS policy

次の場合、クロスオリジンリソースは失敗します。

  • 別のにドメイン
  • 別のにサブドメイン
  • 別のに
  • 別のにプロトコル

CORSはセキュリティのためにあり、悪意のあるユーザーがたまたま使用しているWebプラットフォームを悪用するのを防ぎます。

両方のサーバーを制御する場合そしてクライアント、あなたは両方の当事者が信頼できることを知っているので、リソース共有を許可する正当な理由があります。

どうやって?

サーバー側のスタックによって異なります。

ブラウザのサポート

かなり良い(基本的にIE <10を除くすべて):

CORS browser support

Expressの例

Node.jsとExpressをフレームワークとして使用している場合は、CORSミドルウェアパッケージ

ExpressNode.jsサーバーの簡単な実装は次のとおりです。

const express = require('express')
const app = express()

app.get(’/without-cors’, (req, res, next) => { res.json({ msg: ‘😞 no CORS, no party!’ }) })

const server = app.listen(3000, () => { console.log(‘Listening on port %s’, server.address().port) })

ヒットした場合/without-cors別のオリジンからのフェッチリクエストを使用すると、CORSの問題が発生します。

物事をスムーズに機能させるためにあなたがする必要があるのは、cors上でリンクされたパッケージをミドルウェア関数としてエンドポイントリクエストハンドラーに渡します。

const express = require('express')
const cors = require('cors')
const app = express()

app.get(’/with-cors’, cors(), (req, res, next) => { res.json({ msg: ‘WHOAH with CORS it works! 🔝 🎉’ }) })

/* the rest of the app */

簡単なグリッチの例を作成しました。そのコードは次のとおりです。https://glitch.com/edit/#!/flavio-cors-client

これはNode.jsExpressサーバーです。https://glitch.com/edit/#!/flaviocopes-cors-example-express

サーバーがCORSヘッダーを正しく処理しないために失敗したリクエストが、引き続き受信されることに注意してください。ネットワークパネルでわかるように、サーバーが送信したメッセージを確認できます。

No response from CORS

特定の起源のみを許可する

ただし、この例には問題があります。すべてのリクエストは、クロスオリジンとしてサーバーによって受け入れられます。

ネットワークパネルに表示されているように、渡されたリクエストにはレスポンスヘッダーがありますaccess-control-allow-origin: *

The CORS response header

1つのオリジンのみがサービスを提供できるようにサーバーを構成し、他のすべてのオリジンをブロックする必要があります。

同じを使用してcorsノードライブラリ、これがあなたがそれをする方法です:

const cors = require('cors')

const corsOptions = { origin: https://yourdomain.com, }

app.get(’/products/:id’, cors(corsOptions), (req, res, next) => { //… })

あなたももっと奉仕することができます:

const whitelist = ['http://example1.com', 'http://example2.com']
const corsOptions = {
  origin: function (origin, callback) {
    if (whitelist.indexOf(origin) !== -1) {
      callback(null, true)
    } else {
      callback(new Error('Not allowed by CORS'))
    }
  },
}

プリフライト

「単純な」方法で処理されるいくつかの要求があります。すべてGETリクエストはこのグループに属します。

またいくつか POSTそしてHEADリクエストも同様です。

POSTContent-Typeを使用する要件を満たしている場合、リクエストもこのグループに含まれます。

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

他のすべてのリクエストは、プリフライトと呼ばれる事前承認フェーズを通過する必要があります。ブラウザはこれを実行して、アクションを実行する権限があるかどうかを判断します。OPTIONSリクエスト。

プリフライトリクエストには、サーバーが権限を確認するために使用するいくつかのヘッダーが含まれています(無関係なフィールドは省略されています)。

OPTIONS /the/resource/you/request
Access-Control-Request-Method: POST
Access-Control-Request-Headers: origin, x-requested-with, accept
Origin: https://your-origin.com

The server will respond with something like this (irrelevant fields omitted):

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://your-origin.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE

We checked for POST, but the server tells us we can also issue other HTTP request types for that particular resource.

Following the Node.js Express example above, the server must also handle the OPTIONS request:

var express = require('express')
var cors = require('cors')
var app = express()

//allow OPTIONS on just one resource app.options(’/the/resource/you/request’, cors())

//allow OPTIONS on all resources app.options(’*’, cors())

Download my free Express.js Handbook


More express tutorials: