複数のWebサイトに対してクロスドメイン通信を許可するCORS設定方法

CORS設定は1つしか書けない

CORSを使ったWebアプリケーションを作る際、API等のサービスを提供するサーバに対して複数のドメインからクロスドメイン通信させたい場合があります。しかし、HTTPレスポンスヘッダに書く事ができるCORSは1つだけです。そこで、クラウドデザインパターンです。Multi-CORSパターンと勝手に名付けました。ちなみに、この仕組みはAmazon S3のCORS設定で使われているものです。CORSRuleをXML形式でCORSルールを複数設定できるようになっています。以下はS3のCORS設定サンプルです。今回は、S3と同じようなことをWebAPIを提供するサーバ側で行ってみたいと思います。

<CORSConfiguration>
 <CORSRule>
   <AllowedOrigin>http://www.example.com</AllowedOrigin>

   <AllowedMethod>PUT</AllowedMethod>
   <AllowedMethod>POST</AllowedMethod>
   <AllowedMethod>DELETE</AllowedMethod>

   <AllowedHeader>*</AllowedHeader>
 </CORSRule>
 <CORSRule>
   <AllowedOrigin>*</AllowedOrigin>
   <AllowedMethod>GET</AllowedMethod>
 </CORSRule>
</CORSConfiguration>

概念図

ドメイン毎にCORS設定できるため認証のように使えそうですが、HTTPヘッダ情報はいくらでも偽装可能ですので気をつけて下さい。公開して良い情報にすると、別途認証を行ってから通信するようにしてください。

サンプルコード

このサンプルは、クライアントからHTTPリクエストヘッダを確認して、登録してあるドメインかどうかチェックします。登録されていれば、CORS用のHTTPレスポンスヘッダを付与します。

var http = require('http');

http.createServer(function (req, res) {

  interceptor(req,res);
  res.statusCode = 200;
  res.setHeader('Content-Type','application/json; charset=utf-8');
  res.end('{"name":"bag","price":"1000","timestamp":"'+new Date().toString()+'"}');

}).listen(80);

function interceptor(req, res){
  host = req.headers.host;

  if(checkDomain(host)){
    res.setHeader('Access-Control-Allow-Origin','http://'+host);
    res.setHeader('Access-Control-Allow-Methods','POST, GET, OPTIONS');
    res.setHeader('Access-Control-Allow-Headers','*');
  }
}

function checkDomain(host){
  // Something like DB connection...
  if(host == 'hogehoge.com')return true;
  return false;
}

process.on('uncaughtException', function (err) {
    console.log('uncaughtException => ' + err);
});

まとめ

今回は、CORSを複数設定することで、ドメイン毎にクロスドメイン通信を許可することができる、Multi-CORSパターンをご紹介しました。Amazon S3の新機能にインスパイアされたのですが、S3の利用に限らず汎用的に使える仕組みだと思います。

参考資料

Mashup Standards Part 3: JSONP versus CORS