跨域就是:JavaScript出于安全方面的考虑,不容许跨域调用其余页面的对象。css
但在安全限制的同时也给注入iframe或是ajax应用上带来了很多麻烦。html
简单地理解就是由于JavaScript同源策略的限制,a.com 域名下的js没法操做b.com或是c.a.com域名下的对象。前端
跨域的表现主要有:协议不一样,主机名不一样,端口号不一样node
详细的说明能够看下表:ajax
URL | 说明 | 是否容许通讯 |
---|---|---|
http://www.a.com/a.js http://www.a.com/b.js |
同一域名下 | 容许 |
http://www.a.com/lab/a.js http://www.a.com/script/b.js |
同一域名下不一样文件夹 | 容许 |
http://www.a.com:8000/a.js http://www.a.com/b.js |
同一域名,不一样端口 | 不容许 |
http://www.a.com/a.js https://www.a.com/b.js |
同一域名,不一样协议 | 不容许 |
http://www.a.com/a.js http://70.32.92.74/b.js |
域名和域名对应ip | 不容许 |
http://www.a.com/a.js http://script.a.com/b.js |
主域相同,子域不一样 | 不容许 |
http://www.a.com/a.js http://a.com/b.js |
同一域名,不一样二级域名(同上) | 不容许(cookie这种状况下也不容许访问) |
http://www.cnblogs.com/a.js http://www.a.com/b.js |
不一样域名 | 不容许 |
特别注意两点:json
第一,若是是协议和端口形成的跨域问题“前台”是无能为力的,跨域
第二:在跨域问题上,域仅仅是经过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。
“URL的首部”指window.location.protocol +window.location.host,也能够理解为“Domains, protocols and ports must match”。安全
JSONP包含两部分:回调函数和数据。服务器
回调函数是当响应到来时要放在当前页面被调用的函数。cookie
数据就是传入回调函数中的json数据,也就是回调函数的参数了。
function handleResponse(response){ console.log('The responsed data is: '+response.data); } var script = document.createElement('script'); script.src = 'http://www.baidu.com/json/?callback=handleResponse'; document.body.insertBefore(script, document.body.firstChild); /*handleResonse({"data": "zhe"})*/ //原理以下: //当咱们经过script标签请求时 //后台就会根据相应的参数(json,handleResponse) //来生成相应的json数据(handleResponse({"data": "zhe"})) //最后这个返回的json数据(代码)就会被放在当前js文件中被执行 //至此跨域通讯完成
对于主域相同而子域不一样的例子,能够经过设置document.domain的办法来解决。具体的作法是能够在http://www.a.com/a.html和http://script.a.com/b.html两个文件中分别加上document.domain = ‘a.com’;而后经过a.html文件中建立一个iframe,去控制iframe的contentDocument,这样两个js文件之间就能够“交互”了。固然这种办法只能解决主域相同而二级域名不一样的状况,若是你异想天开的把script.a.com的domian设为alibaba.com那显然是会报错地!代码以下:
www.a.com上的a.html
document.domain = 'a.com'; var ifr = document.createElement('iframe'); ifr.src = 'http://script.a.com/b.html'; ifr.style.display = 'none'; document.body.appendChild(ifr); ifr.onload = function(){ var doc = ifr.contentDocument || ifr.contentWindow.document; // 在这里操纵b.html alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue); };
script.a.com上的b.html
document.domain = 'a.com';
这种方式适用于{www.kuqin.com, kuqin.com, script.kuqin.com, css.kuqin.com}中的任何页面相互通讯。
备注:某一页面的domain默认等于window.location.hostname。主域名是不带www的域名,例如a.com,主域名前面带前缀的一般都为二级域名或多级域名,例如www.a.com实际上是二级域名。 domain只能设置为主域名,不能够在b.a.com中将domain设置为c.a.com。
iframe、img、style、script等元素的src属性能够直接向不一样域请求资源,jsonp正是利用script标签跨域请求资源的简单实现,因此这个和jsonp本质同样,一样须要服务端请求返回callback...形式。
var url="http://xxx.xxx.xxx?p1=1"; var script = document.createElement('script'); script.setAttribute('src', url); document.getElementsByTagName('head')[0].appendChild(script);
flash在跨域时惟一的限制策略就是crossdomain.xml文件,该文件限制了flash是否能够跨域读写数据以及容许从什么地方跨域读写数据。
位于www.a.com域中的SWF文件要访问www.b.com的文件时,SWF首先会检查www.b.com服务器目录下是否有crossdomain.xml文件,若是没有,则访问不成功;若crossdomain.xml文件存在,且里边设置了容许www.a.com域访问,那么通讯正常。因此要使Flash能够跨域传输数据,其关键就是crossdomain.xml。
自flash 10之后,若有跨域访问需求,必须在目标域的根目录下放置crossdomain.xml文件,且该根目录下的配置文件称为“主策略文件”。若不存在主策略文件,则该域将禁止任何第三方域的flash跨域请求。
主策略文件对全站的跨域访问起控制做用。
也能够单独在某路径下放置仅对该路径及其子路径生效的crossdomain.xml配置文件,这须要在flash的AS脚本中使用以下语句来加载该配置文件:[具体的加载权限限制,将受后文中site-control策略的影响]
Security.loadPolicyFile("http://www.xxx.com/subdir/crossdomain.xml") |
crossdomain.xml需严格遵照XML语法,有且仅有一个根节点cross-domain-policy,且不包含任何属性。在此根节点下只能包含以下的子节点:site-control、allow-access-from、allow-access-from-identity、allow-http-request-headers-from。下面将分别介绍这四个子节点:
每一个site-control标签有且仅有属性permitted-cross-domain-policies,该属性指定相对于非主策略文件的其余策略文件的加载策略。permitted-cross-domain-policies属性值有以下状况:
none: 不容许使用loadPolicyFile方法加载任何策略文件,包括此主策略文件。
master-only: 只容许使用主策略文件[默认值]。
by-content-type:只容许使用loadPolicyFile方法加载HTTP/HTTPS协议下Content-Type 为text/x-cross-domain-policy的文件做为跨域策略文件。
by-ftp-filename:只容许使用loadPolicyFile方法加载FTP协议下文件名为 crossdomain.xml的文件做为跨域策略文件。
all: 可以使用loadPolicyFile方法加载目标域上的任何文件做为跨域策略文件,甚至是一 个JPG也可被加载为策略文件![使用此选项那就等着被xx吧!]
如须要对网站某子目录作单独的flash跨域限制策略,在主策略文件中必须进行相应的site-control设置。
下面的例子将site-control策略配置为可加载本服务器中其它的text/x-cross-domain-policy文件做为跨域策略文件。
<cross-domain-policy> <site-control permitted-cross-domain-policies="by-content-type" /> </cross-domain-policy> |
allow-access-from标签有三个属性:
·domain:该属性指定一个确切的 IP 地址、一个确切的域或一个通配符域(任何域)。只有domain中指定的域,才有权限经过flash读取本域中的内容。
可采用下列两种方式之一来表示通配符域:
1.单个星号(*),如:<allow-access-fromdomain="*" />,表示匹配全部域和全部IP 地 址,此时任何域都可跨域访问本域上的内容。[这是极不安全的!]
2.后接后缀的星号,表示只匹配那些以指定后缀结尾的域,如*.qq.com可匹配 game.qq.com、qq.com。形如www.q*.com或www.qq.*的为无效配置。
Tips:当domain被指定为IP地址时,只接受使用该IP做为网址来访问的来源请求[此时ip地址也就至关于一个域名而已],如domain被设置为192.168.1.100时,使用http://192.168.1.100/flash.swf 来请求该域内容是容许的,可是使用指向192.168.1.100的域名www.a.com来访问时[http://www.a.com/flash.swf]将会被拒绝,由于flash不懂得dns解析:)
·to-ports:该属性值代表容许访问读取本域内容的socket链接端口范围。可以使用to-ports="1100,1120-1125"这样的形式来限定端口范围,也可以使用通配符(*)表示容许全部端口。
·secure:该属性值指明信息是否经加密传输。当crossdomain.xml文件使用https加载时,secure默认设为true。此时将不容许flash传输非https加密内容。若手工设置为false则容许flash传输非https加密内容。
下面的例子配置为容许全部qq.com下的全部二级域名[包括qq.com自己]经过https访问本域中的内容。
<cross-domain-policy> <allow-access-from domain="*.qq.com" secure="true" /> </cross-domain-policy> |
<allow-access-from-identity> <signatory> <certificate fingerprint="01:23:45:67:89:ab:cd:ef:01:23:45:67:89:ab:cd:ef:01:23:45:67" fingerprint-algorithm="sha-1"/> </signatory> </allow-access-from-identity> |
allow-access-from节点受权第三域提取本域中的数据,而 allow-http-request-headers-from 节点受权第三方域将数据以http头的形式发送到本域中。[简而言之,allow-access-from是控制读取权限,allow-http-request-headers-from是控制以http头形式的写入权限]
allow-http-request-headers-from包含三个属性:
·domain:做用及参数格式与allow-access-from节点中的domain相似。
·headers:以逗号隔开的列表,代表容许发送的http头。可用通配符(*)表示所有 http头。
·secure:做用及用法与allow-access-from节点中的secure相同。
在下面的示例中,任何域均可以向当前域发送 SOAPAction 标头:
<cross-domain-policy> <allow-http-request-headers-from domain="*" headers="SOAPAction" /> </cross-domain-policy> |
不正确的crossdomain.xml策略将致使严重的安全问题,如信息泄露、CSRF等。从上文中能够看出,在进行安全评估时,咱们应重点关注如下几点:
1.allow-access-from标签的domain属性检测:domain属性应根据最小化原则按需设置,仅容许可信任的来源跨域请求本域内容。禁止将该属性值设置为“*”。
2.allow-http-request-headers-from标签的domain属性检测:domain属性应根据最小化原则按需设置,仅容许可信任的来源向本域跨域发送内容。禁止将该属性值设置为“*”。
3. site-control标签的permitted-cross-domain-policies属性检测:根据业务的实际需求及可行性,对该属性作相应设置。禁止将该属性值设置为“all”。