JSONPを使ってクロスドメイン通信を実現

7722 ワード


概要
Aynch ronous JavaScript and XML(Ajax)は、次世代Webサイト(流行語はWeb 2.0サイト)を駆動する重要な技術である.Ajaxは、Webアプリケーションの表示と動作を妨害しないようにバックグラウンドでデータ検索を可能にする.XMLHttpRequest関数を使用してデータを取得すると、クライアントJavaScriptがHTTPを介してリモートサーバに接続することができるAPIである.Ajaxも多くのmashopの駆動力であり、複数の場所からのコンテンツを単一のWebアプリケーションに統合することができます.
ただし、ブラウザによって制限されているため、この方法はドメイン間通信を許可しない.異なるドメインからデータを要求しようとすると、セキュリティエラーが発生します.データが存在するリモートサーバを制御し、各要求が同じドメインに行くことができれば、これらのセキュリティエラーを回避することができる.しかし、自分のサーバーだけに留まっていたら、Webアプリケーションは何の役に立つだろうか?複数の第三者サーバからデータを収集する必要がある場合、どうすればいいですか?
同源戦略の制限を理解する
ソースポリシーは、フィールドにロードされたスクリプトから他のフィールドの文書属性を取得または操作することを阻止します.つまり、要求されたURLのドメインは、現在のWebページのドメインと同じでなければならない.これは、ブラウザが異なるソースからのコンテンツを分離して、それらの間の操作を防ぐことを意味する.このブラウザのポリシーは古く、Netscape Navigator 2.0バージョンから存在します.
この制限を克服するための比較的簡単な方法は、Webページを元のWebサーバにデータを要求し、ウェブサーバをプロキシのように本物のサードパーティサーバに転送することである.この技術は一般的に使用されているが,伸縮性はない.別の方法は、フレーム要素を使用して、現在のWebページにおいて新しい領域を作成し、GETを使用して、任意の第三者リソースの取得を要求することである.ただし、リソースを取得すると、フレームワークの内容はソースポリシーによって制限されます.
この制限を克服するためのより理想的な方法は、他のドメインのサービスURLを指し、自身のスクリプトからデータを取得する動的スクリプト要素をWebページに挿入することである.スクリプトの読み込み時に実行を開始します.この方法は、同じソースポリシーが動的スクリプトの挿入を阻止しないため、Webページを提供するドメインからスクリプトをロードしたものと見なすことができる.しかし、スクリプトが別のフィールドからドキュメントを読み込むことを試みると、成功しません.幸い、JavaScript Object Notation(JSON)を追加することにより、この技術を改善することができます.
JSONとJSONP
JSONは、ブラウザとサーバとの間で情報を交換するための軽量級データフォーマット(XMLに比べて)です.JOSONはJavaScriptの開発者に依存しています.JavaScriptオブジェクトの文字列表現です.例えば、2つの属性を含むtickerオブジェクトがあると仮定する.これはJavaScriptでtickerオブジェクトを定義する方式です.
var ticker = {symbol: 'IBM', price: 91.42};

 また、これはそのJSONの表示方式である.
{symbol: 'IBM', price: 91.42}

 1.show Price関数を定義する
function showPrice(data) {

    alert("Symbol: " + data.symbol + ", Price: " + data.price);

}

 JSONデータはパラメータとして伝達され、この関数を呼び出すことができます.
showPrice({symbol: 'IBM', price: 91.42}); // alerts: Symbol: IBM, Price: 91.42

 この二つのステップをWebページに含めるつもりです.
 
2.WebページにはshowPrice関数とパラメータが含まれています.
<script type="text/javascript">

function showPrice(data) {

    alert("Symbol: " + data.symbol + ", Price: " + data.price);

}

</script>

<script type="text/javascript">showPrice({symbol: 'IBM', price: 91.42});</script>

 ここでは、本論文では、どのようにして静的JSONデータをパラメータとしてJavaScript関数を呼び出すかを示している.しかし、JSONデータを関数呼び出しで動的データで呼び出すことができます.これは動的JavaScript挿入の技術です.その効果を確認するには、次の行をticker.jsという独立したJavaScriptファイルに入れます.
showPrice({symbol: 'IBM', price: 91.42});

 Webページのスクリプトを変更します.
3.動的JavaScriptコード挿入
<script type="text/javascript">

// This is our function to be called with JSON data

function showPrice(data) {

    alert("Symbol: " + data.symbol + ", Price: " + data.price);

}

var url = “ticker.js”; // URL of the external script

// this shows dynamic script insertion

var script = document.createElement('script');

script.setAttribute('src', url);



// load the script

document.getElementsByTagName('head')[0].appendChild(script); 

</script>

 
3に示す例では、動的に挿入されたJavaScriptコードは、ticker.jsファイルに位置し、本当のJSONデータをパラメータ呼び出しshowPrice()関数として使用する.
前に述べたように、同一ソースポリシーは、動的スクリプト要素をドキュメントに挿入するのを阻止しません.すなわち、異なるドメインからJavaScriptを動的に挿入し、これらのドメインはJSONデータを携帯してもよい.これは本当のJSONP(JSON With Padding)です.関数コールにパッケージされたJSONデータです.なお、この動作を完了するためには、Webページは挿入時に既に定義されているコールバック関数、すなわち私たちの例のshowPrice()を有する必要がある.
しかし、JSONPサービス(またはRemote JSON Service)とは、特定のユーザの関数呼び出しでバックパックしたJSONデータをサポートする付加的な機能を有するWebサービスである.この方法は要求パラメータとしてのコールバック関数名のリモートサービスに依存する.そして、このサービスは、この関数に対する呼び出しを生成し、JSONデータをパラメータとして転送し、クライアントに到達するとウェブページに挿入して実行を開始する.
jQueryのJSONPサポート
1.2バージョンからJSONPに対してはローカルサポートがあります.JSONPコールバックを指定すれば、他のドメインにあるJSONデータをロードすることができ、コールバックの構文はurl?callback=?です.
jQueryは自動的になりますか呼び出したい生成関数名に置換します.リスト4はこのコードを示しています.
4.JSONPコールバックを使う
jQuery.getJSON(url+"&callback=?", function(data) {

    alert("Symbol: " + data.symbol + ", Price: " + data.price);

});

 このため、jQueryはスクリプトを挿入するときに呼び出すウィンドウオブジェクトにグローバル関数を付加します.また、jQueryも非クロスドメイン呼出しを最適化することができます.同じドメインに要求すると、jQueryはそれを普通のAjax要求に変換します.
JSONPサポートを使用した例示的なサービス
前の例では、JavaScriptは、静的ファイルを用いてウェブページに動的に挿入されている.JSONP応答を返しましたが、URLにコールバック関数名を定義することはできません.これはJSONPサービスではありません.それで、どうやって本物のJSONPサービスに変えることができますか?使える方法が多いです.ここではPHPとJavaをそれぞれ使って二つの例を示します.
まず、あなたのサービスが要求されたURLにcallbackというパラメータを受け取ったと仮定します.(パラメータ名は重要ではありませんが、お客様とサーバーはこの名前に同意しなければなりません).また、サービスに送信する要求がこのようなものであると仮定する.
http://www.yourdomain.com/jsonp/ticker?symbol=IBM&callback=showPrice

 この場合、symbolは要求ticker smbolを示す要求パラメータであり、callbackはWebアプリケーションのコールバック関数の名前である.5に示すコードを使用すると、JQueryのJSONPによってサービスを起動することができます.
5.コールバックサービス
jQuery.getJSON("http://www.yourdomain.com/jsonp/ticker?symbol=IBM&callback=?", 

function(data) {

    alert("Symbol: " + data.symbol + ", Price: " + data.price);

});

 
なお、?は、実際の関数名ではなく、コールバック関数名として使用される.jQueryは生成した関数名で?を置換するからです.したがって、showPrice()のような関数を定義する必要はありません.
 6 PHPで実現したJSONPサービスのコードの一部を示しています.
6.PHPで実現したJSONPサービスのコードセグメント
$jsonData = getDataAsJson($_GET['symbol']);

echo $_GET['callback'] . '(' . $jsonData . ');';

// prints: jsonp1232617941775({"symbol" : "IBM", "price" : "91.42"});

 7は同じ機能を持つJavaを示しています.™ Servlet方法
7.Java servletで実現するJSONPサービス
@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) 

  throws ServletException, IOException {

	String jsonData = getDataAsJson(req.getParameter("symbol"));

	String output = req.getParameter("callback") + "(" + jsonData + ");";



	resp.setContentType("text/javascript");

          

	PrintWriter out = resp.getWriter();

	out.println(output);

	// prints: jsonp1232617941775({"symbol" : "IBM", "price" : "91.42"});

}

 
さて、mashopを構築するにはどうすればいいですか?第三者サーバからコンテンツを収集し、単一のWebページに表示しますか?答えは簡単です.第三者のJSONPサービスを利用しなければなりません.このようなサービスは多くないです.
既存のJSONPサービス
JSONPの使い方を知ったら、既存のJSONP Webサービスを利用してアプリケーションやmashを構築することができます.次の開発プロジェクトの準備をします.特定のURLをコピーしてブラウザのアドレスバーに貼り付けて、生成したJSONP応答を確認してください.
Digg API:Diggからのトップニュース:
http://services.digg.com/stories/top?appkey=http%3A%2F%2Fmashup.com&type=javascript

&callback=?

 Geonames API:郵便番号の位置情報:
http://www.geonames.org/postalCodeLookupJSON?postalcode=10504&country=US&callback=?

 Flickr API:Flickrからの最新猫画像:
http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any

&format=json&jsoncallback=?

 Yahoo Local Search API:郵便番号10504の地域でピザを検索する:
http://local.yahooapis.com/LocalSearchService/V3/localSearch?appid=YahooDemo&query=pizza

&zip=10504&results=2&output=json&callback=?

 
重要なヒント
JSONPはmashopの強力な技術を構築していますが、残念なことに、全域にわたる通信に必要な万能薬ではありません.いくつかの欠陥があります.開発資源を提出する前に、真剣に考慮しなければなりません.第一に、JSONP呼び出しに関するエラー処理がないことも重要です.ダイナミックスクリプトの挿入が有効であれば、呼び出しを実行します.無効であれば、沈黙して失敗します.失敗には何のヒントもない.例えば、サーバから404のエラーをキャプチャできないし、要求をキャンセルまたは再開することもできない.でも、しばらく待っても返事がないなら、無視してもいいです.(将来のjQueryバージョンはJSONP要求を終了する特性があります.)
JSONPのもう一つの主要な欠陥は、信頼されていないサービスに利用されると危険です.JSONPサービスは、関数呼び出しでパッケージ化されたJSONに応答するため、関数コールはブラウザによって実行されるので、宿主Webアプリケーションは様々な攻撃を受けやすい.JSONPサービスを利用するつもりなら、それがもたらす脅威を知ることが重要です.