超详细而且带 Demo 的 JavaScript 跨域指南来了!javascript
本文基于你了解 JavaScript 的同源策略,而且了解使用跨域跨域的理由。html
首先要介绍的跨域方法必然是 JSONP。java
如今你想要获取其余网站上的 JavaScript 脚本,你很是高兴的使用 XMLHttpRequest 对象来获取。可是浏览器一点儿也不配合你,无情的弹出了下面的错误信息:git
XMLHttpRequest cannot load http://x.com/main.dat. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://y.com' is therefore not allowed access.
你内心确定会想,我难道要用后台作个爬虫来获取这个数据吗?!(;°○° )
为了不这种蛋疼的事情发生,JSONP 就派上用场了。github
<script>
标签是不受同源策略的限制的,它能够载入任意地方的 JavaScript 文件,而并不要求同源。segmentfault
因此 JSONP 的理念就是,我和服务端约定好一个函数名,当我请求文件的时候,服务端返回一段 JavaScript。这段 JavaScript 调用了咱们约定好的函数,而且将数据当作参数传入。
很是巧合的一点(其实并非),JSON 的数据格式和 JavaScript 语言里对象的格式正好相同。因此在咱们约定的函数里面能够直接使用这个对象。跨域
光说不练假把式,让咱们来看一个例子:浏览器
你须要获取数据的页面 index.html:安全
<script> function getWeather(data) { console.log(data); } </script> <script src="http://x.y.com/xx.js">
http://x.y.com/xx.js 文件内容:框架
getWeather({ "城市": "北京", "天气": "大雾" });
咱们能够看到,在咱们定义了 getWeather(data)
这个函数后,直接载入了 xx.js。
在这个脚本中,执行了 getWeather
函数,并传入了一个对象。而后咱们在这个函数中将这个对象输出到 console 中。
这就是整个 JSONP 的流程。
使用条件:
window
对象的引用。document.domain
默认的值是整个域名,因此即便两个域名的二级域名同样,那么他们的 document.domain
也不同。
使用方法就是将符合上述条件页面的 document.domain
设置为一样的二级域名。这样咱们就可使用其余页面的 window
对象引用作咱们想作的任何事情了。(╯▔▽▔)╯
补充知识:
- x.one.example.com 和 y.one.example.com 能够将
document.domain
设置为 one.example.com,也能够设置为 example.com。document.domain
只能设置为当前域名的一个后缀,而且包括二级域名或以上(.edu.cn
这种整个算顶级域名)。
咱们直接操刀演示,用两个网站 http://wenku.baidu.com/ 和 http://zhidao.baidu.com/。
这两个网站都是 http
协议,端口都是 80, 且二级域名都是 baidu.com。
打开 http://wenku.baidu.com/,在 console 中输入代码:
document.domain = 'baidu.com'; var otherWindow = window.open('http://zhidao.baidu.com/');
咱们如今已经发现百度知道的网页已经打开了,在百度知道网页的 console 中输入如下代码:
document.domain = 'baidu.com';
如今回到百度文库的网页,咱们就可使用百度知道网页的 window
对象来操做百度知道的网页了。例如:
var divs = otherWindow.document.getElementsByTagName('div');
上面这个例子的使用方法并不常见,可是很是详细的说明了这种方法的原理。
这种方法主要用在控制 <iframe>
的状况中。
好比个人页面(http://one.example.com/index.... <iframe>
:
<iframe id="iframe" src="http://two.example.com/iframe.html"></iframe>
咱们在 iframe.html 中使用 JavaScript 将 document.domain
设置好,也就是 example.com。
在 index.html 执行如下脚本:
var iframe = document.getElementById('iframe'); document.domain = 'example.com'; iframe.contentDocument; // 框架的 document 对象 iframe.contentWindow; // 框架的 window 对象
这样,咱们就能够得到对框架的彻底控制权了。
补充知识(绝对干货):
当两个页面不作任何处理,可是使用了框架或者window.open()
获得了某个页面的window
对象的引用,咱们能够直接访问的属性有哪些?
方法 window.blur
window.close
window.focus
window.postMessage
window.location.replace
属性 权限 window.closed
只读 window.frames
只读 window.length
只读 window.location.href
只写 window.opener
只读 window.parent
只读 window.self
只读 window.top
只读 window.window
只读
咱们来看如下一个场景:
随意打开一个页面,输入如下代码:
window.name = "My window's name"; location.href = "http://www.qq.com/";
再检测 window.name
:
window.name; // My window's name
能够看到,若是在一个标签里面跳转网页的话,咱们的 window.name
是不会改变的。
基于这个思想,咱们能够在某个页面设置好 window.name
的值,而后跳转到另一个页面。在这个页面中就能够获取到咱们刚刚设置的 window.name
了。
因为安全缘由,浏览器始终会保持
window.name
是string
类型。
这个方法也能够应用到与 <iframe>
的交互上来。
个人页面(http://one.example.com/index.... <iframe>
:
<iframe id="iframe" src="http://omg.com/iframe.html"></iframe>
在 iframe.html 中设置好了 window.name
为咱们要传递的字符串。
咱们在 index.html 中写了下面的代码:
var iframe = document.getElementById('iframe'); var data = ''; iframe.onload = function() { data = iframe.contentWindow.name; };
定睛一看,为毛线报错?
细心的读者们确定已经发现了,两个页面彻底不一样源啊!
因为 window.name 不随着 URL 的跳转而改变,因此咱们使用一个暗黑技术来解决这个问题:
var iframe = document.getElementById('iframe'); var data = ''; iframe.onload = function() { iframe.onload = function(){ data = iframe.contentWindow.name; } iframe.src = 'about:blank'; };
或者将里面的 about:blank 替换成某个同源页面(最好是空页面,减小加载时间)。
补充知识:
about:blank
,javascript:
和data:
中的内容,继承了载入他们的页面的源。
这种方法与 document.domain
方法相比,放宽了域名后缀要相同的限制,能够从任意页面获取 string
类型的数据。
在 HTML5 中, window
对象增长了一个很是有用的方法:
windowObj.postMessage(message, targetOrigin);
windowObj
: 接受消息的 Window 对象。message
: 在最新的浏览器中能够是对象。targetOrigin
: 目标的源,*
表示任意。这个方法很是强大,无视协议,端口,域名的不一样。下面是烤熟的栗子:
var windowObj = window; // 能够是其余的 Window 对象的引用 var data = null; addEventListener('message', function(e){ if(e.origin == 'http://jasonkid.github.io/fezone') { data = e.data; e.source.postMessage('Got it!', '*'); } });
message
事件就是用来接收 postMessage
发送过来的请求的。函数参数的属性有如下几个:
origin
: 发送消息的 window
的源。data
: 数据。source
: 发送消息的 Window
对象。https://github.com/JasonKid/f...
「JavaScript」两种服务端相关跨域方法详解 ← 反向代理、CORS方法请点这里
以为不错的话按顶部的推荐,让更多人看到吧~ㄟ(▔▽▔ㄟ)