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

使用条件:

  1. 有其他页面 window 对象的引用。

  2. 二级域名相同。

  3. 协议相同。

  4. 端口相同。

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 只读

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:blankjavascript: 和 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

使用条件:

  1. 有其他页面 window 对象的引用。

  2. 二级域名相同。

  3. 协议相同。

  4. 端口相同。

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 只读

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:blankjavascript: 和 data: 中的内容,继承了载入他们的页面的源。

这种方法与 document.domain 方法相比,放宽了域名后缀要相同的限制,可以从任意页面获取 string 类型的数据。

跨域问题实践总结! 上(JSONP/document.domain/window.name)的更多相关文章

  1. 跨域资源请求(除jsonp以外)的方法

    ---------------------------------------------------------------------------------------------------- ...

  2. 解决AJAX跨域:1、利用JSONP;2、JS设置Header

    一.利用JSONP: 首先来看看在页面中如何使用jQuery的ajax解决跨域问题的简单版: $(document).ready(function(){ var url='http://localho ...

  3. [CORS:跨域资源共享] 同源策略与JSONP

    Web API普遍采用面向资源的REST架构,将浏览器最终执行上下文的JavaScript应用Web API消费者的重要组成部分."同源策略"限制了JavaScript的跨站点调用 ...

  4. 用nginx的反向代理机制解决前端跨域问题在nginx上部署web静态页面

    用nginx的反向代理机制解决前端跨域问题在nginx上部署web静态页面 1.什么是跨域以及产生原因 跨域是指a页面想获取b页面资源,如果a.b页面的协议.域名.端口.子域名不同,或是a页面为ip地 ...

  5. 跨域知识(二)——JSONP

    JSONP是服务器与客户端跨源通信的常用方法.最大特点就是简单适用,老式浏览器全部支持,服务器改造非常小. 它的基本思想是,网页通过添加一个<script>元素,向服务器请求JSON数据, ...

  6. 跨域解决方案二:使用JSONP实现跨域

    跨域的实现方式有多种,除了 上篇文章 提到的CORS外,常见的还有JSONP.HTML5.Flash.iframe.xhr2等. 这篇文章对JSONP的跨域原理进行了探索,并将我的心得记录在这里和大家 ...

  7. 前端跨域(二):JSONP

    上一篇文章 前端跨域(一):CORS 实现了跨域的一种解决方案,IE8 和其他浏览器分别通过 XDomainRequest 和 XHR 对象原生支持 CORS.这次我将补一补 Web 服务中也非常流行 ...

  8. JSONP解决跨域问题,什么是JSONP(转)

    原文链接:https://www.cnblogs.com/xinxingyu/p/6075881.html 说到AJAX就会不可避免的面临两个问题,第一个是AJAX以何种格式来交换数据?第二个是跨域的 ...

  9. 利用jquery的ajax实现跨域,内部其实是jsonp协议了,不是XHRhttp协议

    一.同源策略 要理解跨域,先要了解一下“同源策略”.所谓同源是指,域名,协议,端口相同.所谓“同源策略“,简单的说就是基于安全考虑,当前域不能访问其他域的东西. 一些常见的是否同源示例可参照下表: 在 ...

随机推荐

  1. 飞思卡尔IMX6处理器的GPIO配置方式

    在linux或android系统中,假如我们要配置飞思卡尔IMX6处理器的GPIO管脚,比如是GPIO_19这个管脚,那么要像这样: [cpp] view plaincopy #define  MX6 ...

  2. PS 滤镜——素描算法(二)

    利用另外一种算法完成素描特效的生成. %%% Sketch clc; clear all; Image=imread('4.jpg'); Image=double(Image); [row,col,l ...

  3. LeetCode(45)-Bulls and Cows

    题目: You are playing the following Bulls and Cows game with your friend: You write down a number and ...

  4. 恶补web之三:http学习

    http是超文本传输协议的简称,该协议设计目的是保证客户机与服务器之间的通信.http的工作方式为客户机与服务器之间的请求-应答协议. 一般来说web浏览器是客户端,计算机上的网络应用程序可能作为服务 ...

  5. 熊猫猪新系统测试之四:Ubuntu 14.04

    目前猫猪在办公室一般用的就是乌班图系统,一方面原因是老本本性能跑不起来Windows,更重要的是本猫觉得Linux系统更开放些.况且现在用的也比较熟了,完全可以脱离Windows鸟!这一系列4篇新系统 ...

  6. Java IO学习--(三)通道

    Java IO中的管道为运行在同一个JVM中的两个线程提供了通信的能力.所以管道也可以作为数据源以及目标媒介. 你不能利用管道与不同的JVM中的线程通信(不同的进程).在概念上,Java的管道不同于U ...

  7. private static final 修饰符

    java修饰符分类修饰符字段修饰符方法修饰符根据功能同主要分下几种 1.权限访问修饰符 public,protected,default,private,四种级别修饰符都用来修饰类.方法和字段 包外 ...

  8. async/await 的基本实现和 .NET Core 2.1 中相关性能提升

    前言 这篇文章的开头,笔者想多说两句,不过也是为了以后再也不多嘴这样的话. 在日常工作中,笔者接触得最多的开发工作仍然是在 .NET Core 平台上,当然因为团队领导的开放性和团队风格的多样性(这和 ...

  9. [ Java面试题 ]基础篇之一

    1.一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制? 可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致. 2.Java有 ...

  10. Git忽略远程已存在的文件

    git设置本地忽略时远程上不存在本地忽略的文件,git将忽略.如果远程分支上存在这个文件,本地在设置ignore将不起作用.换句话说git本地忽略文件必须保证git的远程仓库分支上没有这个要忽略的文件 ...