JavaScriptのクロスドメイン制限を突破する


JavaScriptはJSファイルが置いてある以外のドメインのファイルをセキュリティの関係上、参照出来ない仕様になっています。
よく他ドメインXMLなどを参照したいときなどこの壁にぶつかりますね。。


この問題を解決する方法はおもに3つあります。

PHPCGIを経由する

これは"JavaScript"→"PHP or CGI"→"参照したいファイル"という順に読み込んでいきます。
設定がとても簡単で一番一般的な方法かもしれません。
CGI等が使用出来る環境でなければならないのが条件です。

XMLを読み込む前提で記述例です。

PHP(ajax.php)

<?php
	if(isset($_GET["url"])) readfile($_GET["url"]);
?>


JavaScript(jQuery)

$(function(){
	$.ajax({
		url:'ajax.php',
		async: true,  
		cache: false, 
		type:'GET',
		dataType:'xml',

		error: function(){
			//読み込みに失敗時の処理
		},

		success: function(xml){
			//読み込みに終了後の処理
		}

	});
});

Flashを経由する

Flashを経由するとCGIPHPが使えない環境でも動作するメリットがあります。
がしかし、"crossdomain.xml"という設定ファイルを読み込みたいデータが置いてあるサーバ側に置かなければなりません。
サーバ管理者でない場合はリスト登録をお願いをすると言うような事が必要になってきます。

crossdomain.xml

<?xml version="1.0"?>
	<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
	<cross-domain-policy>
		<site-control permitted-cross-domain-policies="メタポリシー設定" />
	 	<allow-access-from domain="外部ファイルを読み込む方のドメイン" />
	</cross-domain-policy>

メタポリシー設定

  • all: すべてのポリシーファイルが許可されます。
  • by-content-type: Content-Typeがtext/x-cross-domain-policyのすべてのポリシーファイルが許可されます。
  • by-ftp-filename: FTPサーバにのみ使用できます。
  • master-only: マスターポリシーファイル( /crossdomain.xmlにあります)のみが許可されます。
  • none: ポリシーファイルは許可されません。
  • none-this-response: HTTP応答ヘッダでのみ指定できる特別なメタポリシー。

ドメインの指定

  ※この場合、すべてのドメイン、および IP アドレスからのアクセスが許可される。


追記 2011/7/6
flashで受け取ったXMLflashで処理せずJavaScriptに渡そう(無駄?)とすると以下のようになります。
"crossdomain.xml"が相手サーバーに置いてあるのが前提です。


actionscript(3.0)

import flash.external.ExternalInterface;

var url_loader : URLLoader = new URLLoader();
var url : URLRequest = new URLRequest("読み込みたいXMLのURL");
url_loader.load(url);

url_loader.addEventListener (Event.COMPLETE,LoaderInfoCompleteFunc);

function LoaderInfoCompleteFunc (event : Event) {
	var xml : XML = new XML(url_loader.data);
	ExternalInterface.addCallback("as_function", xml_display);

	function xml_display():String {
		return xml;
	}
}

上記記述の

var url : URLRequest = new URLRequest("読み込みたいXMLのURL");

で読み込みたいXMLのURLを絶対パスで記入してください。また、

ExternalInterface.addCallback("as_function", xml_display);

での、"as_function"はJavaScript側からの呼び出し関数名で、呼び出された際に"xml_display"でXMLの内容を返しています。


JavaScript

function display(){
	var flash = document.as3 || window.as3;
	alert(flash.as_function());
}

上記の記述の

var flash = document.as3 || window.as3;

ででは、クロスブラウザをさせるためのもので変数"flash"のなかに、
IEは"object"タグにid="as3"を設定して、"window.as3"で指定しています。
他ブラウザは"embed"タグに name="as3"を設定して、"document.as3"で指定しています。

alert(flash.as_function());

変数"flash"に入れられたオブジェクトに"as_function()"を実行しています。
これはActionScript側で設定したJavaScriptからの呼び出し用関数名です。


HTML

<object id="as3" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" type="application/x-shockwave-flash" data="sample_03.swf" width="1" height="1">
	<param name="movie" value="sample_03.swf">
	<embed name="as3" src="sample_03.swf" width="1" height="1"></embed>
</object>

<input type="button" onclick="display()" value="click!">

上記HTMLではXMLを読み込ませるためのswfを配置してボタンを押すと"display()"を実行します。


JSONPを使う

JSONJavaScript Object Notation)は、JavaScriptのオブジェクト用の表記をしたデータ形式です。
JavaScriptからは最も利用しやすいデータ形式ですが標準的なファイル形式はXMLな気がします。
このJSON形式をコールバック関数の中にいれた形がJSONPJSON with Padding)です。

PHP

<?php
//getjsonp.php
if(isset($_GET["url"]) && isset($_GET["cb"])){
	header("Content-type: text/javascript;");
	echo $_GET["cb"]."( { data : '";
	echo str_replace("'","\'", str_replace("\n","\\n",file_get_contents($_GET["url"])));

//ファイルを読込み、改行は\\nに変換、クォートをエスケープ。
	echo "'});";
}
?>


JavaScript

//動的に呼び出す関数
function clickGetJSONP( a ) {
	var url = "http://hogehoge.com/getjsonp.php?cb=hoge&url=http://.....?a="+a;
	var sc = document.createElement("script");
	sc.setAttribute("type","text/javascript");
	sc.setAttribute("src", url );
	document.getElementsByTagName("body").item(0).appendChild(sc);
}

//コールバック関数
function hoge( myData) {
	//取得したデータの処理、例えばid="hoge"にそのまま表示させる場合は
	document.getElementById("hoge").innerHTML = myData.data;
}


2011/7/6 「Flashを経由する」の項目を一部追記しました。

記事元:WebTips