JS的跨域
因浏览器的安全原因,Js不能读取和写入本地文件,也不能创建任何到其它web域的网络连接,可以称之为同源策略。使用iframe等方式,可以加载其它域的页面,但两个域的脚本不能互相交互,同时也不能够访问和操作不同域的文档内容和属性。但常有一些合理的情况,需要访问不能域中的资源,在能够保证安全的前提下,如何跨域访问。下面总结了几种方式:
根域相同
根域相同的情况下。可以在两个不同域中的页面都指定document.domain为根域来放宽限制。
例如两个域,a.root.com,和b.root.com,a站用iframe嵌入b站的页面,需要在两个页面中指定 document.domain=root.com,就可以相互操作文档和访问js对象,有时候需要将document.domain放在靠前的位置,避免这句没执行到的时候,已经有互相访问的操作。
有时候被加载页面很多或者其中的域难以改变,也可以使用iframe代理实现。在被加载域中创建一个代理页面,其中将document.domain设置成根域,放置一个ajax请求对象。
然后在当前页面嵌入改代理页面
<iframe src=’http://b.root.com/ajax.proxy.html’ id=’proxy’ name='proxy'></iframe>。
然后可以使用var result = proxy.contentWindow.ajax.request(options)的方式执行。
根域不同
动态创建script标签实现
function request(url) {
var head = document.getElementsByTagName("head").item(0);
oScript = document.createElement("script");
oScript.setAttribute("src", url);
oScript.setAttribute("type","text/javascript");
head.appendChild(oScript);
}
jsonp协议:它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问。服务器端生成的数据格式不同于一般的ajax请求返回结果,而是在结果外包一个函数,类似于callback (data)的函数调用。其中callback为请求发过来的函数名,data为普通方式一样的字符串数据。请求页面定一个一个callback函数,请求完成时该callback函数被调用
使用的时候现在当前页定义onComplete函数,直接request( 'http://otherdomain.com/xxx.php?callback=onComplete&otherparams') 即可。注意这只是一个典型的实现,可以根据需求实现更多的形式,比如一个对象等。
apache代理
通过apache的rewrite方式,将对不同域的请求,转化成相同域的请求。
RewriteEngine on
RewriteRule ^/call_bsite/(.*)$ http://bsite.com/$1
这样可以直接在asite.com站上使用http://asite.com/calll_bsite/xxx.html 来访问http://b_site.com/xxx.html
服务器代理
在服务器端做一个代理页面,动态的抓取远程的内容,
php里面get方式访问很简单,直接echo file_get_contents($url),header('Content-Type: text/xml')。PHP中post请求可使用curl组件或者fsockopen实现
<?php
$post_data = $HTTP_RAW_POST_DATA;
$header[] = "Content-type: text/xml";
$header[] = "Content-length: ".strlen($post_data);
$ch = curl_init( $_GET['url'] );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
if ( strlen($post_data)>0 ){
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
}
$response = curl_exec($ch);
if (curl_errno($ch)) {
print curl_error($ch);
} else {
curl_close($ch);
print $response;
}
?>
AS的跨域
as3中加载外部资源比较复杂,由3个部分控制,策略文件,安全域与应用程序域,使用loader.load和loader.loadBytes加载资源时,通过loaderContext设定。
策略文件
策略文件crossdomain.xml,格式如下,一般放于被加载的域根目录下
<?xml version="1.0" encoding="utf-8"?>
<cross-domain-policy>
<allow-access-from domain=”a.com" secure="true"/>
<site-control permitted-cross-domain-policies="master-only" />
</cross-domain-policy>
策略文件会影响到下面资源的访问
- 位图、声音和视频中的数据:即访问修改图片尺寸、像素点等,显示播放等方法不需要. 如果不需要进行像素级别的访问,则应将checkPolicyFile设为false,减少网络带宽占用
- 加载 XML 和文本文件:
- 将 SWF 文件从其它安全域导入到执行加载的 SWF 文件所在的安全域。不需要访问脚本时不需要策略文件。
- 对套接字和 XML 套接字连接的访问:套接字策略文件所谓位置与格式与上面稍有不同,默认放在843端口。
安全域
加载跨域SWF时,可以指定安全域为null或者当前域,指定为当前域时,相当于将swf下载到本地加载,两者可以互相访问脚本。指定为当前域需要策略文件允许。
应用程序域
这个实际上是一个类的管理机制,只能应用在AS3编写的swf上。子域自动获得当前域的所有类定义,同域则两者的类定义共享,新域则不能相互使用,指定子域和同域时,如果有定义重名,被加载的类定义会被覆盖。
代理方式
即使用服务器端,作为图片、和文本的代理。注意这里不同于js,apache rewrite的代理方式无效,flash检查的是最终url所在域的策略文件。
最简单的php代理<?readfile($dataURL);?>