代理页面处理跨域

xhr(XMLHttpRequest) 的出现,使js可以很容易的获得服务器的数据,但是由于安全的原因,xhr只能取得本域的数据(先
不谈html5 中的跨域xhr),用script元素又失去了xhr的方便易用,让开发者比较头疼。
浏览器有个安全特性, 两个页面的document.domain 相同的时候,两个页面的js 可以互相操作。
利用这个特性, 可以在a域下的页面, 获取在b域下创建的xhr 对象,就可以用这个xhr来请求数据b域下服务器的数据。
原理说了, 看例子吧:

a.sdvil.com 下的test.html 页面, 如例子要请求b.sdvil.com 下的test.php 的数据

    // 设置domain, 使脚本可以跟iframe页面通信
	try{document.domain = window.location.hostname.split('.').reverse().slice(0,2).reverse().join('.');}catch(e){}
	// 取得可以取b.sdvil.com 数据的xhr 对象
	function getXHR(cb) {
		var xmlHttp = null;
		var ifr = document.createElement('iframe');
		ifr.style.display = 'none';

		ifr.src = 'http://b.sdvil.com/ajaxproxy.html';
		var getTransport = function() {
			xmlHttp = ifr.contentWindow.getTransport();
			cb(xmlHttp);
			//找个地方回收iframe,这里还不行,要等ajax 请求完成后才能干掉, 不然xhr对象就没有容器了
			//在chrome下会报错
			//ifr.parentNode.removeChild(ifr);
		}
		// 非ie下 proxy 页面 onload
		ifr.onload = function() {
			getTransport();
		}
		ifr.onreadystatechange = function() {
			// ie下 proxy 页面 onload
			if(ifr.readyState == 'complete') {
				getTransport();
			}
		}
		document.body.appendChild(ifr);
	}
	function xhr(url, callback, ecb) {
		var send = function(xmlHttp) {
			// 哈哈, 用我就可以取得跨域的数据拉
			xmlHttp.onreadystatechange = function() {
				if (xmlHttp.readyState == 4) {
					if (xmlHttp.status == 200) {
						callback(xmlHttp);
						} else {
						ecb();
					}
					delete xmlHttp;
				}
			};
			xmlHttp.open("GET", url, true);
			xmlHttp.send(null);
		}
		getXHR(send);
	}
	function cb(xmlHttp){
		var data=xmlHttp.responseText;
		console.log(data);
		xmlHttp=null;
	}
	function ecb(){
	}
	xhr("http://b.sdvil.com/test.php", cb,ecb);

b.sdvil.com ajaxproxy.html

// 设置domain, 使脚本可以跟iframe页面通信
try{document.domain = window.location.hostname.split('.').reverse().slice(0,2).reverse().join('.');}catch(e){}
// 我获得b.sdvil.com 下的xhr对象
getTransport = function( ) {
	var xmlHttp = null;
	if (window.ActiveXObject) {
		xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
		} else if (window.XMLHttpRequest) {
		xmlHttp = new XMLHttpRequest();
	}
	return xmlHttp;
};

当然这个方法适用在两个域有相同的父域,如果不是的话, 那还是用jsonp 的方式吧
http://api.jquery.com/jQuery.getJSON/

Leave a Comment