Javascript Cross-domain
最近项目中碰到了 IFrame 引入外域页面,设置自由高度无效的情况,此问题涉及到 JS 跨域问题。借此总结一下相关知识。
跨域 :
sometimes we make cross-domain requests, which would usually be prohibited due to the same-domain-policy, javascript same-domain policy prohibit reading of html dom's property at one domain from a different domain. (由于 JavaScript 同源策略的限制,我们无法跨域调用其他页面的 Dom 对象)。
同源策略:
同源策略,它是由 Netscape 提出的一个著名的安全策略,现在所有的可支持 javascript 的浏览器都会使用这个策略。 所谓同源是指,域名,协议,端口相同。
为什么需要同源策略,这里举个例子:
假设现在没有同源策略,会发生什么事情呢?大家知道, JavaScript 可以做很多东西,比如:读取 / 修改网页中某个值。恩,你现在打开了浏览器,在一 个 tab 窗口中打开了银行网站,在另外一个 tab 窗口中打开了一个恶意网站,而那个恶意网站挂了一个的专门修改银行信息的 JavaScript ,当你访问 这个恶意网站并且执行它 JavaScript 时,你的银行页面就会被这个 JavaScript 修改,后果会非常严重!而同源策略就为了防止这种事情发生 .
比如说,浏览器的两个 tab 页中分别打开了 http://www.baidu.com/index.html 和 http: //www.google.com/index.html ,其中, JavaScript1 和 JavaScript3 是属于百度的脚本,而 JavaScript2 是属于谷歌的脚本,当浏览器的 tab1 要运行一个脚本时,便会进行同源检查,只有和 www.baidu.com 同源的脚本才能被执行, tab1 只能执行 JavaScript1 和 JavaScript3 脚本,而 JavaScript2 不能 执行,从而防止其他网页对本网页的非法篡改。
不同环境下的交互情况:
URL |
说明 |
是否允许通信 |
http://www.a.com/a.js |
同一域名下 |
允许 |
http://www.a.com/lab/a.js |
同一域名下不同文件夹 |
允许 |
http://www.a.com:8000/a.js |
同一域名,不同端口 |
不允许
|
http://www.a.com/a.js |
同一域名,不同协议 |
不允许
|
http://www.a.com/a.js
|
域名和域名对应ip |
不允许
|
http://www.a.com/a.js |
主域相同,子域不同 |
不允许 |
http://www.a.com/a.js |
同一域名,不同二级域名(同上) |
不允许(cookie 这种情况下也不允许访问) |
http://www.cnblogs.com/a.js |
不同域名 |
不允许 |
解决方案一,加个代理服务
Web 页面向它源自的 Web 服务器请求数据,并且让 Web 服务器像代理一样将请求转发给真正的第三方服务器。
《 JavaScript: Use a Web Proxy for Cross-Domain XMLHttpRequest Calls 》
解决方案二 插入动态脚本 ( JSONP )
SONP 即 JSON with Padding 。由于同源策略的限制, XmlHttpRequest 只允许请求当前源(域名、协议、端口)的资源。如果要进行跨域请求,我们可以通过使用 html 的 script 标记来进行跨域请求,并在响应中返回要执行的 script 代码,其中可以直接使用 JSON 传递 javascript 对象。这种跨域的通讯方式称为 JSONP 。我们可以简单这样理解: JSONP 就是可以通过 JavaScript 文件进行跨域通讯的方式
JSONP 实例
我们可以首先定义一个函数来执行 JSONP 返回的数据,然后通过 JSONP 的 src 传此函数给后台,进行处理,返回可执行的函数。例如下面代码:
function jsonpCallback (a){ alert(a); } var JSONP = document.createElement("script") ; JSONP.type = "text/javascript"; JSONP.src = "http://js8.in/jsonp.php?callback=jsonpHandle"; //在head之后添加js文件 document.getElementsByTagName("head")[0].appendChild(JSONP);
url 是跨域服务器取 json 数据的接口,参数为回调函数的名字,返回的格式为 :
jsonpCallback({msg:'this is json data'})
Jsonp 原理:
首先在客户端注册一个 callback, 然后把 callback 的名字传给服务器。
此时,服务器先生成 json 数据。
然后以 javascript 语法的方式,生成一个 function , function 名字就是传递上来的参数 jsonp.
最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。
客户端浏览器,解析 script 标签,并执行返回的 javascript 文档,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里 . (动态执行回调函数)