理解JSONP
被问到如何绕开浏览器中javascript的同源策略时,大多数人会提到JSONP这个方案,或许也会提到其他方案(比如代理或者CORS),但是并不能清楚的解释究竟哪种方案更好。这篇文章会回答上述问题。
一、JSONP是什么?
如果你熟知javascrpt在浏览器中的运行机制,你可能知道通过script标记的src属性引入的脚本不受同源策略的限制。例如,当我们从Google的cdn节点或者其他源加载jquery库时,它跟我们的当前页面并不是同源的。
同理,利用script标记可以尝试加载除了库文件之外的其它类型的javascript。由于javascript有一个全局作用域,设想你用script标签加载的文件中执行了一个全局的函数,这个函数的参数是你应用中要用到的数据,这就是JSNOP的实现思路。
JSONP的实现思路很简单:
在文档中插入一个script标签,这个标签引用一个返回json数据的资源。服务器端返回的是加了装饰的JSON,即返回的是函数执行,而结果数据被作为函数执行的参数使用的,因此服务器端的api必须也要支持JSONP。通常,在请求JSONP接口时,函数名必须作为callback参数传递。举例,假设你访问一个返回JSON格式的天气信息的服务,接口如下:
http://www.weather.com/90210
这个接口返回的JSON格式的数据是这样的
{"zipCode": "90210","location": "Beverly Hills","high": "85 degrees","low": "55 degrees"}
服务端api支持JSONP的话,接口是这样的
http://www.weather.com/90210?callback=MyCallback
返回的数据格式是这样的
MyCallback({"zipCode": "90210","location": "Beverly Hills","high": "85 degrees","low": "55 degrees"});
只要MyCallback是全局作用域中的有效函数,json数据在程序的其他地方是可访问的。
在jquery这样的前端库中,JSONP的实现方式是自动生成一个回调函数,当回调函数执行时会立刻将插入的script标记删除。
二、为什么要用JSONP
- 主流浏览器都支持JSONP,此外很多API服务也支持JSONP的形式调用。
- 一个XMLHttpRequest请求和DOM的改动就可以以低成本实现跨浏览器
- 主流的前端库和框架都实现了JSONP
三、JSONP的缺点
- jsonp是通过script标记实现的,所以只能用GET方法。不符合Restful api的设计规范,同时也只能用url params的方式传参。
- jsonp依赖script标记,没有统一的捕获错误的机制。不是所有些浏览器都可以去侦听script的相应的事件,因此不得不使用hacks
- jsonp绕开了同源策源,为程序带来了安全隐患
四、JSONP的替代方案
- 配置代理 在服务器上对于非同源的外部API设置代理,例如在Ngnix上,设置proxy_pass字段
- HTTP访问控制(CORS)
如果不考虑IE7及以下浏览器,也不用关心opera,CORS是实现跨域最好的方案。理由如下
- 支持所有HTTP请求方式
- 支持错误捕获
- 安全系数高
- IE8+浏览器支持,并且在服务器端实现简单
缺点就是主流JSONP APIs还不支持
五、结论
CORS >= Proxy > JSONP
原文地址:
https://johnnywey.wordpress.com/2012/05/20/jsonp-how-does-it-work/