jQueryを使ったAjax通信(クロスドメイン編)

jQueryでのAjaxについては実案件でもポツポツ使ってましたが、Ajax呼び出し元とサーバーが同じドメインのケースばっかりで、
サーバーのドメインが異なるケースについては詳しくなかったので、再確認しました。

業務系Webシステムを作ってるとあまり使わない気がしないでも無いですが、例えば他システムのWebAPIをAjaxで呼んだりするかもしれません。
あと、PhoneGapを使う場合は必須になるのではないでしょうか。


以下、サンプルを記述しました。
サーバー側プログラムはSAStrutsですが、他言語でも内容はほとんど変わらないと思います。

同じドメインでのAjaxの例

サーバー側プログラム

@Execute(validator=false)
public String normalAjax()
{
	String data = "{\"id\" : \"A001\",\"name\" : \"山田太郎\"}";
	ResponseUtil.write(data);
	return null;
}

HTML側

$.ajax({
	url : 'normalAjax',
	success : function(data)
	{
		var jsonData = $.parseJSON(data);
		alert(jsonData.name);
	},
	error : function(data)
	{
		alert('Error!');
	},
	complete : function(data)
	{
		
	}
});

HTMLとサーバーが同じドメインで動作していれば、これで問題なく動作するはずです。
しかし例えばHTMLファイルをディスクに保存してそこから実行すると、うまくいかなくなります。
(当然、urlの変更が必要です。)

JSONPで解決するパターン
JSONPを使う場合、ajaxの呼び出しを下記のように変更します。

HTML側

$.ajax({
	url : 'http://localhost:8080/xxx/jsonpAjax',
	dataType : 'jsonp',
	success : function(data)
	{
		alert(data.name);
	},
	error : function(data)
	{
		alert('Error!');
	},
	complete : function(data)
	{
		
	}
});

サーバー側も、JSONPとしてのレスポンスを返すようになっている必要があります。

@Execute(validator=false)
public String jsonpAjax()
{
	String data = request.getParameter("callback") + "({\"id\" : \"A001\",\"name\" : \"山田太郎\"});";
	ResponseUtil.write(data);
	return null;
}

HTMLからjQuery経由でアクセスすると、こんな形でレスポンスが返って来ます。

jQuery1710505071623176485_1332744836123({"id" : "A001","name" : "山田太郎"});

これで、HTMLとサーバーが別ドメインでも結果を取得することができます。


Access-Control-Allow-Originヘッダーで解決するパターン
レスポンスヘッダーにAccess-Control-Allow-Originを指定することで、別ドメインのサーバーにAjaxでアクセスすることができるようになります。

HTML側

$.ajax({
	url : 'http://localhost:8080/xxx/acaoAjax',
	success : function(data)
	{
		var jsonData = $.parseJSON(data);
		alert(jsonData.name);
	},
	error : function(data)
	{
		alert('Error!');
	},
	complete : function(data)
	{
		
	}
});

HTML側は、通常のAjaxと同じです。

サーバー側プログラム

@Execute(validator=false)
public String acaoAjax()
{
	response.setHeader("Access-Control-Allow-Origin","*");
	String data = "{\"id\" : \"A001\",\"name\" : \"山田太郎\"}";
	ResponseUtil.write(data);
	return null;
}

レスポンスヘッダーの1行を加えるだけで、HTMLとサーバーが別ドメインでも結果を取得することができます。

ただ、Access-Control-Allow-Originは全てのブラウザーが対応しているわけではないようで、IE6とかIE7では使えませんでした。
こちら(XMLHttpRequest level2に対応しているブラウザまとめ at HouseTect, JavaScriptな情報をあなたに)を参考にさせていただきました。


まとめ
○クロスドメインでのAjax通信をする場合、サーバー側での設定が必要
これはセキュリティ上仕方のないことです。
サーバープログラムの実装を自分で作るときはJSONPかACAOかを選択できると思いますが、いずれにしろ
通信するデータの中身と使い方について十分注意する必要がありそうです。