导航
导航
文章目录
  1. 什么是跨域
  2. 为什么跨域
  3. 怎么跨域
  4. JSON 和 JSONP
  5. 通过 JSONP 跨域
    1. JSONP 的产生
    2. JSONP 的实现

跨域问题解决方案之 JSONP

什么是跨域

由于浏览器同源策略的限制,为了保证安全,是不能执行其他网站的脚本的,通俗点来说,就是执行的 URL 不在你的网站下。跨域即绕过同源策略的限制,获取其他网站的数据。

同源的定义:协议,域名,端口均相同。

简单说明对 http://mrzhouxiaofei.com/test.js 的同源检测情况:

为什么跨域

一般公司内部都会有许多不同的子域,举个例子,比如百度,假设 pan.baibu.com 需要获取用户的信息,就要去 user.baidu.com 下去获取,前者访问后者的数据就属于跨域,除此之外,引用其他网站的各种资源也属于跨域,总之,跨域的使用范围还是很广的。

怎么跨域

跨域的方式有许多种,主要有 JSONP,CORS,以及通过 document.domain 来跨子域等等,感兴趣的可以了解一下其它几种跨域方式,本篇文章将主要介绍目前使用较多的 JSONP 方式。

JSON 和 JSONP

介绍通过 JSONP 跨域之前,先理解 JSON 和 JSONP 这两个概念。

JSON 不用多解释,之前接触的也比较多,它是一种数据交换格式,在它出现之前,XML 曾一统天下,它出现之后,抢夺了 XML 的半壁江山,并且越来越流行。

JSON 的优点:

  1. 基于纯文本,跨平台传递极其简单;
  2. JavaScript 原生支持,后台语言几乎全部支持;
  3. 轻量级数据格式,占用字符数量极少,特别适合互联网传递;
  4. 可读性较强

JSONP (JSON with Padding)是数据格式 JSON 的一种“使用模式”,可以让网页从别的网域要数据,也即跨域获取数据。简单来说,JSONP 就是一种开发人员创造出的非官方跨域数据交互协议。学过计算机网络的同学,应该比较容易理解什么是协议。

通过 JSONP 跨域

JSONP 的产生

我们知道,通过 ajax 请求文件存在跨域无权访问时,无论你是什么网页,一律不被允许,不过我们一定有过这种情况:

  1. 通过 script 标签引入过域外文件,比如引入百度的 JQuery;
  2. 通过 img 标签引入过于在线的图片;

通过以上两种情况,我们发现 Web 页面上调用 Js 文件或引用图片是不受跨域影响的,进一步发现,凡是拥有 src 这个属性的标签,都拥有跨域的能力。

这样以来服务器把客户端需要的数据封装成包含 JSON 的 Js 文件 ,客户端就可以通过 script 标签,调用服务器动态生成的 Js 文件,来实现跨域获取数据了。

客服端获取数据后,就可以对数据经行处理了,这看起来非常 ajax,但其实并不一样。

为了便于客户端使用数据,逐渐形成了一种非正式的传输协议,这种协议就是 JSONP,该协议的一个特点就是允许用户传递一个 callback 参数给服务器,然后服务器返回数据时会将这个 callback 参数作为函数名来包裹住 JSON 数据,这样客户端就可以随意定制自己的函数来自动处理返回的数据了。

JSONP 的实现

1.假设远程服务器 mrzhouxiaofei.com 根目录下有这样一个文件 test.js

1
alert("我是远程数据")

本地服务器 localhost 下有个 index.html

1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
</head>
<body>
<script src="http://mrzhouxiaofei.com/test.js"></script>
</body>
</html>

毫无疑问,页面弹出一个提示框,显示跨域调用成功。

2.假设远程服务器 mrzhouxiaofei.com 根目录下有这样一个文件 test.js

1
doSomething({"info": "我是远程数据"})

本地服务器 localhost 下有个 jsonp.html 页面,其中定义了一个函数,然后在远程 test.js 中传入数据进行调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
</head>
<body>
<script>
var doSomething = function(data) {
alert("远程数据:" + data.info)
}
</script>
<script src="http://mrzhouxiaofei.com/test.js"></script>
</body>
</html>

运行之后,页面弹出提示窗口,并且跨域获取了远程的数据,但是怎么让服务器知道它应该调用哪个客户端的函数呢?

3.这次先写本地服务器 localhost 下的 jsonp.html 的代码,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
</head>
<body>
<script>
var doSomething = function(data) {
alert("远程数据:" + data.info)
}
var script = document.createElement('script')
script.src = "http://mrzhouxiaofei.com/test.js?callback=doSomething"
document.getElementsByTagName('body')[0].appendChild(script)
</script>
</body>
</html>

这次的代码不再写死,而是实现了动态查询,而这正是 JSONP 实现的核心部分,通过代码,可以看到,客户端调用的 URL,传入了一个 callback 参数,告诉服务器我的本地函数为 doSomething,这时服务器就会把客户端需要的数据传入到这个函数内,供客户端的调用,这样就完成了一次请求过程。

远程服务器将要返回的数据如下:

1
2
3
4
doSomething({
"id": 1001,
"info": "我是远程数据"
})

到此为止,客户端就能跨域获取数据了,另外一点,JSONP 只能发送 GET 请求,不能发送 POST 请求

说明:该文章部分内容参考 【原创】说说JSON和JSONP,也许你会豁然开朗,含jQuery用例 ,看不懂的,可以看看这篇文章。