「JavaScript」JS四种跨域方式详解
原文地址https://segmentfault.com/a/1190000003642057
超详细并且带 Demo 的 JavaScript 跨域指南来了!
本文基于你了解 JavaScript 的同源策略,并且了解使用跨域跨域的理由。
1. JSONP
首先要介绍的跨域方法必然是 JSONP。
现在你想要获取其他网站上的 JavaScript 脚本,你非常高兴的使用 XMLHttpRequest 对象来获取。但是浏览器一点儿也不配合你,无情的弹出了下面的错误信息:
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 就派上用场了。
<script> 标签是不受同源策略的限制的,它可以载入任意地方的 JavaScript 文件,而并不要求同源。
所以 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 的流程。
2. document.domain
使用条件:
有其他页面
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.blurwindow.closewindow.focuswindow.postMessagewindow.location.replace
属性 权限 window.closed只读 window.frames只读 window.length只读 window.location.href只写 window.opener只读 window.parent只读 window.self只读 window.top只读 window.window只读
3. window.name
我们来看以下一个场景:
随意打开一个页面,输入以下代码:
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 类型的数据。
4. [HTML5] postMessage
在 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对象。
Demo
https://github.com/JasonKid/f...
两种服务端相关跨域方法
「JavaScript」两种服务端相关跨域方法详解 ← 反向代理、CORS方法请点这里
觉得不错的话按顶部的推荐,让更多人看到吧~ㄟ(▔▽▔ㄟ)
「JavaScript」JS四种跨域方式详解的更多相关文章
- 「JavaScript」四种跨域方式详解
超详细并且带 Demo 的 JavaScript 跨域指南来了! 本文基于你了解 JavaScript 的同源策略,并且了解使用跨域跨域的理由. 1. JSONP 首先要介绍的跨域方法必然是 JSON ...
- JAVA中的四种JSON解析方式详解
JAVA中的四种JSON解析方式详解 我们在日常开发中少不了和JSON数据打交道,那么我们来看看JAVA中常用的JSON解析方式. 1.JSON官方 脱离框架使用 2.GSON 3.FastJSON ...
- thinkphp四种url访问方式详解
本文实例分析了thinkphp的四种url访问方式.分享给大家供大家参考.具体分析如下: 一.什么是MVC thinkphp的MVC模式非常灵活,即使只有三个中和一个也可以运行. M -Model 编 ...
- Android学习笔记_50_(转 四种加载方式详解(standard singleTop singleTask singleInstance)
Android之四种加载方式 (http://marshal.easymorse.com/archives/2950 图片) 在多Activity开发中,有可能是自己应用之间的Activity跳转,或 ...
- Android 四种加载方式详解(standard singleTop singleTask singleInstance) .
Android之四种加载方式 (http://marshal.easymorse.com/archives/2950 图片) 在多Activity开发中,有可能是自己应用之间的Activity跳转,或 ...
- VirtualBox的四种网络连接方式详解
VirtualBox中有4中网络连接方式: 1. NAT 2. Bridged Adapter 3. Internal 4. Host-only Adapter VMWare中有三种,其实他跟VMWa ...
- SpringDI四种依赖注入方式详解
文章已托管到GitHub,大家可以去GitHub查看阅读,欢迎老板们前来Star!搜索关注微信公众号 [码出Offer] 领取各种学习资料! LOGO SpringDI(依赖注入) 一.DI概述 De ...
- Javascript几种跨域方式总结
在客户端编程语言中如javascript,同源策略规定跨域之间的脚本是隔离的,一个域的脚本不能访问和操作另外一个域的绝大部分属性和方法.只有当两个域具有相同的协议,相同的主机,相同的端口时,我们就认定 ...
- 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之十二 || 三种跨域方式比较,DTOs(数据传输对象)初探
更新反馈 1.博友@落幕残情童鞋说到了,Nginx反向代理实现跨域,因为我目前还没有使用到,给忽略了,这次记录下,为下次补充.此坑已填 2.提示:跨域的姊妹篇——<三十三║ ⅖ 种方法实现完美跨 ...
随机推荐
- "《算法导论》之‘线性表’":基于数组实现的单链表
对于单链表,我们大多时候会用指针来实现(可参考基于指针实现的单链表).现在我们就来看看怎么用数组来实现单链表. 1. 定义单链表中结点的数据结构 typedef int ElementType; cl ...
- GraphCuts算法解析,Graphcuts算法求最大流,最小割实例
图割论文大合集下载: http://download.csdn.net/detail/wangyaninglm/8292305 代码: /* graph.h */ /* Vladimir Kolmog ...
- VS2010 / MFC + OpenCV 2.4.9打开图片
原文地址:http://www.opencv.org.cn/forum.php?mod=viewthread&tid=30832 第一部分,参考http://jingyan.baidu.com ...
- os X下mds_stores占用大量cpu的解决办法
有时候发现, MacOS中, 有个叫做mds_stores的进程占了好多CPU, 于是要阻止这个行为, 据说这是MacOS在建索引然后只要把这个索引的关掉就好了 sh-3.2# mdutil -a - ...
- Hibernate中配置文件的学习
首先我们看一下hibernate的主配置文件 <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Conf ...
- HBase最佳实践 - 集群规划
本文由 网易云发布. 作者:范欣欣 本篇文章仅限本站分享,如需转载,请联系网易获取授权. HBase自身具有极好的扩展性,也因此,构建扩展集群是它的天生强项之一.在实际线上应用中很多业务都运行在一个 ...
- Golang适合高并发场景的原因分析
http://blog.csdn.NET/ghj1976/article/details/27996095 典型的两个现实案例: 我们先看两个用Go做消息推送的案例实际处理能力. 360消息推送的数据 ...
- Java杂记9—NIO
前言 非阻塞IO,也被称之为新IO,它重新定义了一些概念. 缓冲buffer 通道 channel 通道选择器 BIO 阻塞IO,几乎所有的java程序员都会的字节流,字符流,输入流,输出流等分类就是 ...
- Niop2017初赛滚粗记
初赛踢蹬滚粗 TOT (╯°Д°)╯︵┻━┻ ヽ(`Д´)ノ︵ ┻━┻ ┻━┻ 排序啊排序,净是排序,自打我学了C++就再没学过排序!!wtf! (╯°Д°)╯︵ /(.□ . )我tm怎么知道建国那 ...
- 部署SSIS包完成远程数据更新
** 温馨提示:如需转载本文,请注明内容出处.** 本文连接:http://www.cnblogs.com/grom/p/9018978.html 笔者需要定期从服务器更新N家客户的远程服务器数据,上 ...