什么是跨域
由于浏览器同源策略的限制,为了保证安全,是不能执行其他网站的脚本的,通俗点来说,就是执行的 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 的优点:
- 基于纯文本,跨平台传递极其简单;
- JavaScript 原生支持,后台语言几乎全部支持;
- 轻量级数据格式,占用字符数量极少,特别适合互联网传递;
- 可读性较强
JSONP (JSON with Padding)是数据格式 JSON 的一种“使用模式”,可以让网页从别的网域要数据,也即跨域获取数据。简单来说,JSONP 就是一种开发人员创造出的非官方跨域数据交互协议。学过计算机网络的同学,应该比较容易理解什么是协议。
通过 JSONP 跨域
JSONP 的产生
我们知道,通过 ajax 请求文件存在跨域无权访问时,无论你是什么网页,一律不被允许,不过我们一定有过这种情况:
- 通过 script 标签引入过域外文件,比如引入百度的 JQuery;
- 通过 img 标签引入过于在线的图片;
通过以上两种情况,我们发现 Web 页面上调用 Js 文件或引用图片是不受跨域影响的,进一步发现,凡是拥有 src 这个属性的标签,都拥有跨域的能力。
这样以来服务器把客户端需要的数据封装成包含 JSON 的 Js 文件 ,客户端就可以通过 script 标签,调用服务器动态生成的 Js 文件,来实现跨域获取数据了。
客服端获取数据后,就可以对数据经行处理了,这看起来非常 ajax,但其实并不一样。
为了便于客户端使用数据,逐渐形成了一种非正式的传输协议,这种协议就是 JSONP,该协议的一个特点就是允许用户传递一个 callback 参数给服务器,然后服务器返回数据时会将这个 callback 参数作为函数名来包裹住 JSON 数据,这样客户端就可以随意定制自己的函数来自动处理返回的数据了。
JSONP 的实现
1.假设远程服务器 mrzhouxiaofei.com 根目录下有这样一个文件 test.js
alert("我是远程数据")
本地服务器 localhost 下有个 index.html
<!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
doSomething({"info": "我是远程数据"})
本地服务器 localhost 下有个 jsonp.html 页面,其中定义了一个函数,然后在远程 test.js 中传入数据进行调用
<!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 的代码,代码如下:
<!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,这时服务器就会把客户端需要的数据传入到这个函数内,供客户端的调用,这样就完成了一次请求过程。
远程服务器将要返回的数据如下:
doSomething({
"id": 1001,
"info": "我是远程数据"
})
到此为止,客户端就能跨域获取数据了,另外一点,JSONP 只能发送 GET 请求,不能发送 POST 请求。
说明:该文章部分内容参考 【原创】说说JSON和JSONP,也许你会豁然开朗,含jQuery用例 ,看不懂的,可以看看这篇文章。