SSブログ

必要に迫られてクロスドメイン制約を勉強してみた [プログラミング]

 久方ぶりの更新です。今日はプログラミングネタです。
 javascript+jqueryで外部サイトにアクセスするローカルhtmlファイルを書き,ブラウザで動かして遊んでいるが,このアプリをandroidタブレット上のブラウザで動かそうとしたらうまく動かない。いろいろ試してみたら,そもそもPC上のブラウザも,いつも使っているsafariでは動くものの,firefoxやchromeでは動かないことに気づいた。
 いろいろぐぐってみると「クロスドメイン制約」というものに引っかかっているらしい。一体何者? なぜsafariだけ大丈夫なのか?

[1] ドメインとは何か
 ドメインとはインターネット上の住所のことで,例えば https://blog.so-net.ne.jp/MyPage/blog/article/regist/input というurlのページであれば,https://blog.so-net.ne.jp がドメインらしい。これに続く /MyPage/blog/article/regist/input はドメイン内の部屋割りみたいなものか。
 なお,PC内のローカルファイルであれば,file:///で始まってフォルダ名が続いた後のファイル名までがドメインとなるようだ。

[2] クロスドメイン制約とは何か
 さて,あるドメインにあるファイルに書かれたjavascriptコードから同じドメインにあるサイトにアクセスするのでなく,別のドメインのサイトにアクセスする場合,これをクロスドメイン(アクセス)と呼ぶらしい。
 クロスドメインについては(なぜかsafariを除き)ブラウザが厳しい制約を設けているらしく,ワタクシがはまった例では,jqueryの$.get関数でyahooのホームページ http://www.yahoo.co.jp/ を呼び出そうとしたら,safari以外では開発ツールにこういうメッセージが出る。
 XMLHttpRequest cannot load http://www.yahoo.co.jp/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
 和訳すると「XMLHttpRequest(ローカルPCからサーバーにアクセスするための仕組み)は http://www.yahoo.co.jp/ をロードできない。これは http://www.yahoo.co.jp/ がAccess-Control-Allow-Originヘッダを持っていないために,呼び出し側が持っているnullオリジン(ドメインとほぼ同義)はアクセスを許されない」となる。
 つまりどういうことかというと,http://www.yahoo.co.jp/ が例えば「Access-Control-Allow-Origin: *」というヘッダを明示的に持っていればどのドメインからのアクセスも許可するが,それがないのでブラウザがアクセスを自主規制するようだ。
 なお,この自主規制は単なるXMLHttpRequestだけでなく,win=window.open()で取得したwindowオブジェクトに対してjqueryのセレクタ$("...",win.document)を使うことも「Uncaught DOMException: Blocked a frame with origin "null" from accessing a cross-origin frame.」として禁止される。

[3] ブラウザの立場の違い
 ここで重要なのは,safariだけjqueryの$.get関数が使えるからといって,http://www.yahoo.co.jp/ がsafariからのXMLHttpRequestにだけ返信しているわけではないということである。http://www.yahoo.co.jp/ はどのブラウザからのXMLHttpRequestであっても平等にレスポンスを返しているのである。事実,ブラウザの開発ツールで http://www.yahoo.co.jp/ からのレスポンスが200(成功)であることが確認できるが,http://www.yahoo.co.jp/ はAccess-Control-Allow-Originヘッダを返さないことで「レスポンスはするもののそれをブラウザのjavascriptコードか使うことを推奨しない」と主張しているのだ。
 このレスポンスに対してどう対応するかはブラウザ側の問題である。繰り返すように,safariはローカルPCユーザーのリスク管理能力を信じてyahooの主張を無視するが,firefoxやchromeはローカルPCユーザーのリスク管理能力を信じていないためにyahooの主張を尊重するということなのだろう。

[4] クロスドメイン制約の回避策
 ぐぐってみるとクロスドメイン制約の回避策がいろいろ出てくるが,正攻法は「ローカルPCからはクロスドメインアクセスを行わず,サーバー上のスクリプトコードからクロスドメインアクセスを行う」ことに尽きる。
 先ほど,呼び出された側が「レスポンスはするもののそれをブラウザのjavascriptコードか使うことを推奨しない」と主張していると述べたものの,サーバー上のスクリプトについてはローカルPC上のブラウザが行うような自主規制がそもそも存在しないのだろう。
 あとは簡単で,ローカルPC上のブラウザから呼び出すサーバー上のスクリプトについて「Access-Control-Allow-Origin: *」というヘッダを明示的に持たせておけばよい。レンタルサーバーを使う手もあるが,ワタクシのようにノーコストでやりたい場合はgoogle apps scriptを使えばよい。google apps scriptで提供されるウェブサイトは「Access-Control-Allow-Origin: *」というヘッダを明示的に持っているので,ローカルPCとの自由なアクセスが可能。

※(2017/02/25追記)ただし,google apps scriptからの戻り値がHtmlService.createHtmlOutput()では「Access-Control-Allow-Origin: *」ヘッダが振られず,ContentService.createTextOutput()のような明示的なテキスト形式でなければならない模様。

おしまい。
nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

※ブログオーナーが承認したコメントのみ表示されます。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。