跨域问题实践总结! 上(JSONP/document.domain/window.name)
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-----------------这个方法有点问题,执行iframe.src之后iframe中的页面刷新后变量就消失了,取不到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 类型的数据。
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 类型的数据。
跨域问题实践总结! 上(JSONP/document.domain/window.name)的更多相关文章
- 跨域资源请求(除jsonp以外)的方法
---------------------------------------------------------------------------------------------------- ...
- 解决AJAX跨域:1、利用JSONP;2、JS设置Header
一.利用JSONP: 首先来看看在页面中如何使用jQuery的ajax解决跨域问题的简单版: $(document).ready(function(){ var url='http://localho ...
- [CORS:跨域资源共享] 同源策略与JSONP
Web API普遍采用面向资源的REST架构,将浏览器最终执行上下文的JavaScript应用Web API消费者的重要组成部分."同源策略"限制了JavaScript的跨站点调用 ...
- 用nginx的反向代理机制解决前端跨域问题在nginx上部署web静态页面
用nginx的反向代理机制解决前端跨域问题在nginx上部署web静态页面 1.什么是跨域以及产生原因 跨域是指a页面想获取b页面资源,如果a.b页面的协议.域名.端口.子域名不同,或是a页面为ip地 ...
- 跨域知识(二)——JSONP
JSONP是服务器与客户端跨源通信的常用方法.最大特点就是简单适用,老式浏览器全部支持,服务器改造非常小. 它的基本思想是,网页通过添加一个<script>元素,向服务器请求JSON数据, ...
- 跨域解决方案二:使用JSONP实现跨域
跨域的实现方式有多种,除了 上篇文章 提到的CORS外,常见的还有JSONP.HTML5.Flash.iframe.xhr2等. 这篇文章对JSONP的跨域原理进行了探索,并将我的心得记录在这里和大家 ...
- 前端跨域(二):JSONP
上一篇文章 前端跨域(一):CORS 实现了跨域的一种解决方案,IE8 和其他浏览器分别通过 XDomainRequest 和 XHR 对象原生支持 CORS.这次我将补一补 Web 服务中也非常流行 ...
- JSONP解决跨域问题,什么是JSONP(转)
原文链接:https://www.cnblogs.com/xinxingyu/p/6075881.html 说到AJAX就会不可避免的面临两个问题,第一个是AJAX以何种格式来交换数据?第二个是跨域的 ...
- 利用jquery的ajax实现跨域,内部其实是jsonp协议了,不是XHRhttp协议
一.同源策略 要理解跨域,先要了解一下“同源策略”.所谓同源是指,域名,协议,端口相同.所谓“同源策略“,简单的说就是基于安全考虑,当前域不能访问其他域的东西. 一些常见的是否同源示例可参照下表: 在 ...
随机推荐
- LeetCode之“数学”:Rectangle Area
题目链接 题目要求: Find the total area covered by two rectilinear rectangles in a 2D plane. Each rectangle i ...
- 速度之王 — LZ4压缩算法(一)
LZ4 (Extremely Fast Compression algorithm) 项目:http://code.google.com/p/lz4/ 作者:Yann Collet 本文作者:zhan ...
- Linux之ulimit详解(整理)
修改:一般可以通过ulimit命令或编辑/etc/security/limits.conf重新加载的方式使之生效通过ulimit比较直接,但只在当前的session有效,limits.conf中可以根 ...
- linux上搭建ftp服务器
摘要 vsftpd 是"very secure FTP daemon"的缩写,安全性是它的一个最大的特点.vsftpd 是一个 UNIX 类操作系统上运行的服务器的名字,它可以运行 ...
- log4j日志的配置
在项目开发中,记录错误日志方便调试.便于发现系统运行过程中的错误.便于后期分析, 在java中,记录日志有很多种方式,比如说log4j log4j需要导入的包: commons-loggin.jar ...
- java实习面试题(阿里一面)
1.抽象类和接口的不同点: 抽象类可以有构造函数,接口中不能有构造函数: 抽象类中可以有普通成员变量,但是接口中不能有普通成员变量: 抽象类中可以包含非抽象的普通方法,但是接口中必须是抽象方法:(jd ...
- 使用javascript中读取Xml文件做成的一个二级联动菜单
[html] view plaincopy <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> ...
- Apache Flink Quickstart
Apache Flink 是新一代的基于 Kappa 架构的流处理框架,近期底层部署结构基于 FLIP-6 做了大规模的调整,我们来看一下在新的版本(1.6-SNAPSHOT)下怎样从源码快速编译执行 ...
- 【抽象那些事】不完整的抽象&多方面抽象&未用的抽象&重复的抽象
不完整的抽象 抽象未支持所有互补或相关的方法时,将导致这种坏味. 为什么要有完整的抽象? 一种重要的抽象实现手法是创建内聚而完整的抽象.抽象未支持相关的方法时,可能会影响抽象的内聚性和完整性.如果抽象 ...
- VirtualBox虚拟机网络设置(四种方式)
原文地址: https://www.douban.com/group/topic/15558388/ VirtualBox的提供了四种网络接入模式,它们分别是: 1.NAT 网络地址转换模式(NAT, ...