スポンサーサイト

一定期間更新がないため広告を表示しています

  • 2013.01.21 Monday
  • -
  • -
  • -
  • -
  • by スポンサードリンク

クロスドメインで使う XMLHttpRequest と JSONP のお話

技術的な話です、サーセン。

最近、必須技術となってきた XMLHttpRequest ですが、別ドメインへアクセスできません。

それを何とかしようという話。実は JSONP とは何者なのか?という話が本題。
簡単な例を挙げますと、XMLHttpRequest オブジェクトでは www.mydomain.com のページ内から www.otherdomain.com の提供するサービスにはアクセスできません。ドメインが違うからです。

これはこまった。

というわけで・・・

そこで登場したのが JSONP です。

思いっきり話がそれるんですが、JSONP の前身、JSON について説明を残しておきますか。だって、昨日まで知らなかったんだもん^^

XMLHttpRequest は、どこぞのウェブアプリに接続してその結果を取得してくる仕組みになっています。基本は XML ですが、取得してきたものはXMLとエラそうな名前がついてますけど、もっと突っ込めばただのテキストデータなわけです。別にXMLじゃなくてもいいんです。じゃあ・・・

クソめんどいXMLより扱いやすいデータ形式でくれよ。

が JSON の発想だと思われます。では JavaScript で扱いやすいデータ形式とは何か?

JavaScript ですよね。

JavaScript で利用するデータなんだから JavaScript の形式が一番処理しやすいわけです。そんなわけで JSON では、JavaScript のオブジェクト(もしくは配列?)定義スクリプトを返します。

{"name":"山田太郎","sex":"男","age":20}


こんな感じです。こんなデータもらっても「解析しろってか?」「どこが処理しやすいの?」て感じですが eval 関数という素敵な関数があるわけです。文字列をスクリプトとして処理してくれます。

var xhr = new XMLHttpRequest();
xhr.open("GET", "http://www.mydomain.com/xxxxx", false);
xhr.send(null);

var json = xmlHttp.responseText;
var obj = eval( "(" + json + ")" );
alert(obj.name); // 取ってきたデータから名前(name)を表示


注) 取得したスクリプトを eval に与えるときに括弧でくくっているのはブラウザによってはエラーが発生するからです。本来そんなことをする理由はないはずなのですがなぜでしょうね?マイクロソフトさん。prototype.js も JSON を扱う際にはこの手法を使っているそうです。

これでめんどくさい XML DOM API とはおさらばです。なんてすばらしい。しかも新規に覚えることはゼロ。だって新しい技術が全くないんですもの。まぁ、クロスドメインですし、他人のサーバのスクリプトをまるまる信用して動かす必要があるわけなので、クロスサイトに関するセキュリティ対策はしっかり考えておくべきです。が、それにしても楽。なんで昨日まで無視し続けていたんでしょう?

新しい言葉作んなよ!
覚えるのめんどくさいんだよ!
スルーしちゃうんだよ!

JSON は JavaScript Object Notation の略です。グーグル先生による直訳は「JavaScriptのオブジェクト表記法」です。まさにその通り。

そんな JSON ですが、ただのデータ形式にすぎないわけです。結局のところ XMLHttpRequest を使う限り、クロスドメインの壁は越えられないわけです。

やっと話が戻ります。

そこで登場したのが JSONP です。JSON に P が付いたわけですが JSON with Padding の略らしいです。グーグル先生による直訳は「JSONとパディング」です。

まんま過ぎる(#^ω^)

まぁ、その、XMLHttpRequest ではドメインの壁を越えられないわけです。じゃあ、既存の方法で超えられる方法はなにか?

script タグです。

script タグの src 属性に別ドメインのアプリを指定してデータを取得するんです。

<script type='text/javascript' src='http://www.otherdomain.com/xxxx'>


これで別ドメインからデータを取得することができました。しかし、そのデータが JSON であろうが XML であろうがまともに動作しません。ちゃんと動くスクリプトじゃないんだもの。そこで Padding です。グーグル先生による直訳は「詰め物」です。

<script type='text/javascript' src='http://www.otherdomain.com/xxxx?callback=getJSON'>


パラメータに callback が付きました。このパラメータの名前はなんでもいいです。アクセス先のサービスによって変わってきます。

で、このパラメータを受け取ったサービス側はどうするか?このパラメータで指定された値を関数名とみなしてJSONデータをくるんでやります(詰め物)。

getJSON({"name":"山田太郎","sex":"男","age":20});


これで script タグで取得して動くスクリプトになりました。あとは取得する側に callback 関数(ここでは getJSON 関数)を実装してやればドメインの壁を突破です。

<script type='text/javascript''>
var obj;
function getJSON(json) {
obj = json;
}
</script'>


実際に使う場合には、フォームの入力値等を前提としてアクセスを行うことが多いと思われます。実際に使う場合には script タグを直接書く方法はあまり使わないんじゃないかと思います。

var element = document.createElement("script"); // script タグを生成
element.src = "http://www.otherdomain.com/xxxx?callback=getJSON";
document.body.appendChild(element); // body にノードを追加(この時点で読み込み:非同期)


script タグを生成して body に突っ込むのは非同期です。ブラウザがレスポンスを取得して、スクリプトを解析して、スクリプトが実行されて初めてそのあとの処理ができるようになることに気を付けてください。処理を行う前に、グローバル変数に「JSON データが格納されているか?」チェックとか、コールバック関数で「取得しました!」フラグを立てたりする必要がありそうです。

例ではコールバック関数で詰め物しましたが、サイトによってはパラメータの指定した名前の変数にいれるスクリプトを返してくるサービスもあるかもしれません。ないと思いたい。

var getJSON = {"name":"山田太郎","sex":"男","age":20};


もしかすると変数名固定のアホなサービスもあるかもしれません。この方法、JSONP の言葉の意味を考えると邪道な気がします。というか違うだろ。ですが、この方法でも動作はします。コールバック関数が必要ない分、実装が楽だし。そこらはサービス次第ですし、自分サイト内のAPI用としては実装が楽でいいかもしれません。

しかしながら JSON に対応したサービスもいまのところ半々といった感じに見受けられます。なおかつ JSONP と言われると・・・結構な大手しか対応していないと思います。というか対応を考えないサービスもあるかもしれません。対応して"もらわないとダメ"てのは非常に大きな制限ですよね。JSON は他の言語でも使えるとはいえ、他言語で使うとするとはやり解析する必要があるわけで・・・めんどくさい。じゃあ、どの言語からでも使える XML だけでいいと判断するサービスもあるでしょう。つまり、

いつでもどこでも使える対策ではない。

クロスドメインを何とかする話ですが、できない理由を考えてみます。

やばいから

それ以上に説明できるセリフがないんですが、何がやばいのか?

JavaScript は、ユーザのブラウザ操作のほとんどをトレースできます。
JavaScript は、ファイルを読み込めます。
JavaScript は、ネット上のどこかへデータを送信できます。

やばいですよね?

@IT - Ajaxの特徴に潜むリスクをサンプルアプリで確認しよう
http://www.atmarkit.co.jp/fwcr/special/ajax_kaitai02/03.html

上のページに一例があります。ここの例では、マウス操作を記録して記録したマウス操作を再現するスクリプトが例に上がっています。マウス操作くらい・・・と侮ってはいけません。ログイン操作をトレースされたらどうなるでしょう?マウスじゃなくてキーボードだったらどうでしょう?ユーザ・パスワードともにモロバレです。さらにどこかに送信されてしまったらどうでしょう?

もちろん "自由にできたら" ていう条件になりますが、だからこそ "自由にできない" ように制限がかかっているわけです。そんな理由だからこそ、今後、制限が解除されることは考えられないでしょう。

なんでこんな解説までつけたかっていうと・・・

そのうち script, iframe タグの src で読むのも制限されそう・・・
果ては img タグもアウトになるかもね・・・

今は使えるけど、そのうち使えなくなる方法かもね。

これが言いたかった

とすると、ここまで長々と JSONP の説明をしてきたけど

ブラウザ上でクロスドメイン対応をやるのはあきらめてしまえ。

という結論になりそうです。

使えなくなることはないと思うけどw

とりあえずプロクシを作るのが一番シンプルかつ確実に思えます。どこかに他サーバアクセス用のアプリを作ってしまうのです。もちろん Web アプリからなら同ドメインのどこかに、です。

それが一番簡単。かつ確実。将来のとうとつな制限にも強そう。PHP で書くならば

<?php echo file_get_contents('http://www.otherdomain.com/xxxx');


これだけですよ。大抵の場合、相手に送信するパラメータは動的になるはずなのでそこらの処理が増えますが、大した量ではないでしょう。

ほんの少し汎用的にして、ほんの少しセキュリティを考えたらこんなもんですか?

<?php
$url = isset( $_GET['url'] ) ? $_GET['url'] : null;
if ( is_null($url) or trim($url) == '' ) {
    exit;
}

$url = urldecode($url);
if ( preg_match('/^http/', $url) === 1 ) { // http 以外(file://とか)をスルーする
    if ( isset($_GET['format']) and $_GET['format'] == 'xml' ) {
        // フォーマットがXMLならヘッダを出力してやる
        header('Content-type: application/xml');
    }
    echo file_get_contents($url);
}


もう少し考えるなら、referrer なんかをチェックして自ドメインのページ以外からのリクエストをはじいたりするといいかもしませんし、サニタイズ処理を加えて出力するのもいいかもしれません。がっつりやるなら Socket 開いてレスポンスヘッダやステータスコードも処理したいところです。

あとは iframe を利用するやり方もあるようです。説明しているサイトもあったんですが・・・「相手サーバになんらかの静的ページが必要」というくだりをみて考えるのをやめました。それ、相手サーバが用意してくれるの?

XMLHttpRequest Level 2 というものもあるみたい。こういうのありがたいけどブラウザ依存だから解決しないことがおおいのよね・・・。


結論


ブラウザ上でやるのはあきらめてしまえ。

そうもいかない(プロクシを置ける場所がない)なら・・・

サービスそのものの利用をあきらめてしまえ。

あきらめたらそこで試合終了だよ

どーしたものか。


余談になりますが、IE6 は余裕のクロスドメインです。IE9になっても警告がでるだけです。マイクロソフト的には、その時点で責任をユーザになすりつけてしまっているので問題ないのでしょうけども、使う側はそれでは困ります。IE を使うな!というのは、このあたりが理由ですよね。警告なんて意味ないんですよ。何を警告されてるのかさっぱりわからないんだから。警告なんて余裕のスルーですよね。

もう1個蛇足ですが、なんか今回の記事すごいエラそう・・・

続いちゃった → 続 クロスドメインで使う XMLHttpRequest と CORS の話

スポンサーサイト

  • 2013.01.21 Monday
  • -
  • 18:28
  • -
  • -
  • -
  • by スポンサードリンク

コメント
2013年の新素材-新作!高品質の追求、品質保証、超A品を良心価格で提供します!

詳しくは以下のようなブランドがあります。
HERMES(バッグ、小物、時計) CHANEL(バッグ、小物、時計)
LOUIS VUITTON(バッグ、小物、衣類、時計) BVLGARI(小物、時計)
Christian Dior(バッグ、小物) COACH(バッグ、小物
GUCCI(バッグ、小物) ROLEX(時計)
OMEGA(時計) IWC(時計)
FRANCK MULLER(時計)
クロエ CHLOE バッグなどです
1.当社の目標は品質第一、信用第一、ユーザー第一の原則を守り、心地よい親切で最高のインターネットサービスご提供することです。

2.品質を重視、納期も厳守、信用第一は当社の方針です。

3.弊社長年の豊富な経験と実績があり。輸入手続も一切は弊社におまかせてください。質が一番、最も合理的な価格の商品をお届けいたします。

4.お届け商品がご注文内容と異なっていたり、欠陥があった場合には、全額ご返金、もしくはお取替えをさせていただきます。

弊社は「信用第一」をモットーにお客様にご満足頂けるよう
1.当社の目標は品質第一、信用第一、ユーザー第一の原則を守り、心地よい親切で最高のインターネットサービスご提供することです。

2.品質を重視、納期も厳守、信用第一は当社の方針です。

3.弊社長年の豊富な経験と実績があり。輸入手続も一切は弊社におまかせてください。質が一番、最も合理的な価格の商品をお届けいたします。

4.お届け商品がご注文内容と異なっていたり、欠陥があった場合には、全額ご返金、もしくはお取替えをさせていただきます。

弊社は「信用第一」をモットーにお客様にご満足頂けるよう
◆100%品質保証!満足保障!リピーター率100%!
■主な販売2013年最新作ブランドコピー新品.
●(louis vuitton)、(MIUMIU)、(Chanel)、(GUCCI)
●(CHLOE)、(PRADA)、(BVLGARI)、(HERMES)、(COACH)
●(D&G)、(BALENCIAGA)、各種ブランドバッグ、時計、財布.
■品質がよい、価格が低い、実物写真!
◆送料は無料です!安心して買って下さい! (*^-^*)
サンローランコピー
2013s/sよりYves Saint Laurent(イヴサンローラン)から改名。
Saint Laurent(サンローラン)は「モードの帝王」との異名を持つ、アルジェリア出身のデザイナー、イヴ・サンローランが1962年に発表したブランドです。

http://www.wabag2016.com/yslbag01.html

ブランド激安菊田店舗を提供する!

wabagjp@gmail.com

連絡お待ちしております!
ブランドコピー財布
ブランド特集!
http://inspiredraw.com
http://wabag2016.com
http://wdxshop.com
lnnbag2016.com

割引情報:
1.注文金額10000円以上:贈る送ルイヴィトンコインケースやキーケース 1個
2.注文金額19800円以上:贈る送ルイヴィトン財布 1個
3.注文金額38800円以上:贈る送ルイヴィトンバッグ 1個
注意:注文は多くて、特恵は多いです

inspiredraw@yahoo.co.jp
コメントする








   
この記事のトラックバックURL
トラックバック

calendar

S M T W T F S
      1
2345678
9101112131415
16171819202122
23242526272829
3031     
<< July 2017 >>

最近の記事

記事(カテゴリ別)

リンク

recent comment

recent trackback

  • 続 クロスドメインで使う XMLHttpRequest と CORS の話
    RougeBleu (07/31)

ブログ内検索

others