Ajax 浏览器跨域访问控制

蹲街弑〆低调 提交于 2019-11-29 05:18:58

jsonp+ajax实现浏览器跨域通信的原理解析

php+ajax+P3P实现多域名跨域登录

一.关于跨域需要设置的响应头消息

Access-Control-Allow-Origin:*                               #允许所有主机
Access-Control-Allow-Origin:http://hello-world.example      #允许特定主机

Access-Control-Allow-Methods: POST, GET, OPTIONS            #允许跨域执行的方法

Access-Control-Allow-Headers: X-PINGOTHER,Content-Type,MyHeader                  #允许跨域设置的头信息(如果不设置,那么无法获取该值,甚至数据无法获取)

Access-Control-Max-Age: 1728000

 

二.关于IE8和IE9浏览器差异性说明 

IE8和IE9使用新的API   XDomainRequest(IE又淘气了一次,但还好IE7上可以通过ajax跨域)

var xdr = new XDomainRequest();
   xdr.onload = function (e) { //当收到服务器响应的回调函数
            var data = $.parseJSON(xdr.responseText);
            if (data == null || typeof (data) == 'undefined') {
                data = $.parseJSON(data.firstChild.textContent);
            }
            //success
   };
  xdr.onerror = function (e) {
            //error
   }

xdr.open("GET", url); //目前只支持IE8和IE9
xdr.send();

对于webkit阵营的浏览器而言,需要使用ajax,这里我们不在多演示,我们将在下面做一个兼容性的例子。

 

三.为了达到兼容性的指标,我们进行如下改造

设立一站点 www.a.com,作为请求的client

<!doctype html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>Cross-Domain</title>
		<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
	</head>
	<body>
	<script type="text/javascript" charset="utf-8">
	var xdr = null;
	if(!!window.XMLHttpRequest)
	{
		xdr = new XMLHttpRequest();
	}
	else if( window.ActiveXObject)
	{
		try
		{ //IE7+
			xdr = new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch (e) 
		{
			//IE6-
			try { xdr = new ActiveXObject("Microsoft.XMLHTTP");} catch (e) { } 
		}
	}

	if(xdr)
	{		
        	if(!("withCredentials" in xdr) && window.XDomainRequest) 
        	{
        		xdr = new XDomainRequest();
        	}else{
        		xdr['withCredentials'] = true;
        	}
        				
        	if(window.XMLHttpRequest && (xdr instanceof XMLHttpRequest))//如果是IE6,IE7,chrome,firefox,IE10,IE11
        	{
        		xdr.open('OPTIONS', 'http://www.b.com/html5/crossdomain-server.php', true);
        	}
        	else if(window.ActiveXObject&&(xdr instanceof XDomainRequest))//如果是IE8,IE9
        	{
        		xdr.open("POST", "http://www.b.com/html5/crossdomain-server.php");
        	}
				
	
		xdr.onload = function(e) 
		{
			xdr.onReadyStateChange(arguments);  
		};

		xdr.onReadyStateChange = function(e)
		{
			if(window.console)
			{
				console.dir(xdr.responseText);
			}else{
				alert(xdr.responseText);
			}
		}
					
		 xdr.send(null);
	}
	else
	 {
		alert('Not Supported !');
	 }	

		</script>
	</body>
</html>

 

设立服务器站点   www.b.com/html5/crossdomain-server.php

<?php
header('Content-Type:application/json;charset=utf-8');
header('Pragma:no-cache,no-store');
header('Cache-Control:no-cache,private');
header('Date:'+date('r'));
header('Connection:Keep-Alive');

header('Access-Control-Allow-Origin: http://www.a.com');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS,PUT,DELETE,HEAD');
header('Access-Control-Allow-Headers: X-PINGOTHER,Content-Type,Accept,Range');
header('Access-Control-Max-Age: 1728000');
header('Access-Control-Allow-Credentials: true');

date_default_timezone_set('Asia/Chongqing');

$data = array(
	'id'  => 'ZF1024',
	'name'=>'zhangsan',
	'token'=>uniqid()
);


echo json_encode($data);

?>

 

请求结果

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

三.html5 postMessage 进行跨域

a.com/index.html中的代码:

<iframe id="ifr" src="b.com/index.html"></iframe>
<script type="text/javascript">
window.onload = function() {
    var ifr = document.getElementById('ifr');
    var targetOrigin = 'http://b.com';  // 若写成'http://b.com/c/proxy.html'效果一样
                                        // 若写成'http://c.com'就不会执行postMessage了
    ifr.contentWindow.postMessage('I was there!', targetOrigin);  //通过这句穿透域名限制
};
</script>
b.com/index.html中的代码:

<script type="text/javascript">
    window.addEventListener('message', function(event){
        // 通过origin属性判断消息来源地址
        if (event.origin == 'http://a.com') {
            alert(event.data);    // 弹出"I was there!"
            alert(event.source);  // 对a.com、index.html中window对象的引用
                                  // 但由于同源策略,这里event.source不可以访问window对象
        }
    }, false);

 

最后,你还可以通过apache服务器设置跨域

<IfModule mod_setenvif.c>
    <IfModule mod_headers.c>
        <FilesMatch "\.(cur|gif|ico|jpe?g|png|svgz?|webp)$">
            SetEnvIf Origin ":" IS_CORS
            Header set Access-Control-Allow-Origin "*" env=IS_CORS
        </FilesMatch>
    </IfModule>
</IfModule>

 

参考:http://www.cnblogs.com/rainman/archive/2011/02/20/1959325.html#m2

         http://msdn.microsoft.com/zh-cn/library/gg589525(v=vs.85).aspx

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!