はじめに
今どきのブラウザはではルールに従うことでクロスドメイン(クロスオリジン)のAJAXが出来ます。ルールというのは最低限、AJAXで取得するデータがある先のサーバがAccess-Control-Allow-Origin
ヘッダを返すことです。
ただしこの仕様には関連ヘッダがやたら沢山あるので、やりたいことにたいして適切な設定するには記事後半の関連ヘッダまとめまで目を通しておくことをおすすめします。
単純なケースの .htaccess による設定例(オリジンの許可例)
これらの設定サンプルは認証を必要としないシンプルなGETリクエストでCORSを行う為の設定です。
全て許可
一番簡単なのは以下のような設定です。これを .htaccess ファイルに書いておけばそのサイト上のコンテンツは他サイトから取得し放題ということになります。
Header set Access-Control-Allow-Origin "*"
特定ドメインからのAJAX取得を許可
自分が管理している一つないしは数個程度のドメインからのみAJAX取得を許可したい場合は以下のようにします。
Header set Access-Control-Allow-Origin "http://www.example.jp"
数個程度のオリジンであれば以下のように空白区切りで列挙可能です。
Header set Access-Control-Allow-Origin "http://www.example.jp https://www.example.jp http://sub.example.jp"
特定サブドメインからのAJAX取得を許可
これはちょっと面倒です。 *.example.jp
といった値が指定できれば良いのですが、仕様では http://www.example.jp などといった完全な形のオリジンか、全部許可の*
か、全部拒否のnull
しか指定することが出来ず、部分的なワイルドカードは許可されていません。
なので仕方がないので mod_rewrite を使って以下のように対応します。
###簡易版
以下の設定は*.example.jp
への許可と同じように動作します。ホントは受け取ったOriginをそのまま返してやってもいいのですが、どうせRewriteCondで既に制限されている部分なのでとりあえず*
を返して済ましています。
RewriteCond %{HTTP:Origin} \.example\.jp$
RewriteRule . - [E=CORS_OK:1]
Header set Access-Control-Allow-Origin "*" env=CORS_OK
###クレデンシャル(CookieとかBASIC認証)対応版
クレデンシャルを必要とする場合は*
での許可は使えないので注意が必要です。やっぱりキチンと許可オリジンを明記してやる必要があります。以下は送られてきたOriginを許可オリジンとしてオウム返しする設定です。これならクレデンシャルを扱う場合も対応できてベストですね。
RewriteCond %{HTTP:Origin} (.+\.example\.jp)$
RewriteRule . - [E=CORS_ORIGIN:%1]
Header set Access-Control-Allow-Origin %{CORS_ORIGIN}e env=CORS_ORIGIN
その他
関連ヘッダー
シンプルなGETだけなら↑これだけでよいですが、認証用のCookieを受け入れたりPOSTメソッドを受け入れたりも出来るようにしたりなどを考えてるなら、他にも以下のヘッダについても学んでおく必要があります。必要になったら調べましょう。
-
オリジンチェック (これは上で説明した)
-
Origin
Request Header (オリジンを伝える、これはCORSの際にブラウザが自動で送信するものでJSによる指定は出来ない) -
Access-Control-Allow-Origin
Response Header (許可オリジンを列挙、半角空白区切り) -
これらが一致しないと、仮にコンテンツが返ってきたとしてもブラウザはレスポンスを捨てるため使用できない。
-
クレデンシャルチェック(Cookie,BASIC認証ヘッダの使用許可、更にJS側はxhr.withCredentials=trueも必要)
-
Access-Control-Allow-Credentials
Response Header (クレデンシャル情報の使用許可を true|false で返す) -
認証が必要なコンテンツを取得する場合に必要な手順。
-
この許可が無いと、仮にコンテンツが返ってきたとしてもブラウザはレスポンスを捨てるため使用できない。
-
メソッドチェック(GET以外のメソッドを使いたい場合はプリフライトリクエストで確認が入る)
-
Access-Control-Request-Method
Request Header (使用希望メソッドを一つだけ表明) -
Access-Control-Allow-Methods
Response Header (使用可能メソッドを全て列挙して返す) -
これらが一致しないと、ブラウザは実際のリクエストを行わない。
-
レスポンスヘッダの使用許可(プリフライトリクエストで確認が入る)
-
Access-Control-Request-Headers
Request Header (使用希望リクエストヘッダ名を表明、カンマ区切り) -
Access-Control-Allow-Headers
Response Header (使用希望されたヘッダ名を列挙して許可する、カンマ区切り) -
Access-Control-Expose-Headers
Response Header (↑に関係なく使用可能なリクエストヘッダをサーバが列挙、カンマ区切り) -
これらが一致しないと、ブラウザは実際のリクエストを行わない?もしくはそのヘッダを送らない?(要確認)
-
プリフライトリクエストのレスポンスに対するキャッシュ許可
-
Access-Control-Max-Age
Response Header (プリフライトリクエスト結果のキャッシュ可能期限を秒数で指示) -
繰り返し行われるCORSリクエスト毎にプリフライトリクエストするのはちょっと無駄だしね。
jQuery でCORSするするときにやるべきこと。
-
$.support.cors = true;
をajax実行前にセットしておく。これやらないとそもそもCORS出来ません。 - それからクレデンシャル使う場合はajaxオプションに
xhrFields: {withCredentials: true}
も追加しておく。認証情報を使わない/使いたくない場合は指定不要。