作者:Bob Ippolito /原文链接
浏览器安全模型规定,XMLHttpRequest、框架(frame)等只能在一个域中通信。从安全角度考虑,这个规定很合理;但是,也确实给分布式(面向服务、混搭等等本周提到的概念)Web开发带来了麻烦。
为了实现跨域通信,通常的解决方案有3种:
本地代理:
需要一些硬件设施(没有服务器的客户端无法运行),并且带宽和潜伏时间也要加倍(远程服务器-代理服务器-客户端)。
Flash:
远程主机中需要部署一个crossdomain.xml文件,而且,Flash作为一门专有技术,其前途尚不明朗;换句话说,开发人员很可能要学习一种目标不确定的编程语言。
Script标签:
无法确切知道内容是否有效,没有标准的实现方法,又可能被认为是一种“安全风险”。
在此,我建议使用一种新技术,也是一种独立于标准的方法,即通过script标签来跨域获取数据,名为JSON with Padding,或者就叫JSONP。JSONP的原理很简单,但需要服务器端给予相应配合。大致来说,JSONP的实现思路就是在客户端编程时作好使用JSON数据的准备,然后再通过圆括号将这些数据括起来以创建一条有效的JavaScript语句(可能是一次有效的函数调用)。
也就是说,客户端可以使用一个用于命名jsonp的查询参数来决定可以获取的数据。最简单的情况下,如果jsonp参数为空,则返回的数据就是被括在圆括号中的JSON。
下面,我们就以del.icio.us的JSON API为例,来说明JSONP的原理。该API有一个“script tag”变量(即,可以将下面的URL作为script标签的src属性值,用以加载del.icio.us这个API提供的数据。——译者注)如下所示:
http://del.icio.us/feeds/json/bob/mochikit+interpreter:
if(typeof(Delicious) == 'undefined') Delicious = {};
Delicious.posts = [{
"u": "http://mochikit.com/examples/interpreter/index.html",
"d": "Interpreter - JavaScript Interactive Interpreter",
"t": [
"mochikit","webdev","tool","tools",
"javascript","interactive","interpreter","repl"
]
}]
如果用JSONP的方式来表示,那么与此具有相同语义的URL应该是这样的:
http://del.icio.us/feeds/json/bob/mochikit+interpreter?jsonp=if(typeof(Delicious)%3D%3D%27undefined%27)Delicious%3D%7B%7D%3BDelicious.posts%3D
单纯看这个URL似乎没有什么,但我们可以要求服务器在数据有效时给出通知。因此,我可以编写一个用于跟踪数据的小系统:
var delicious_callbacks = {};
function getDelicious(callback, url) {
var uid = (new Date()).getTime();
delicious_callbacks[uid] = function () {
delete delicious_callbacks[uid];
callback();
};
url += "?jsonp=" + encodeURIComponent("delicious_callbacks[" + uid + "]");
// add the script tag to the document, cross fingers
};
getDelicious(doSomething, "http://del.icio.us/feeds/json/bob/mochikit+interpreter");
根据以上假设,用于获取数据的URL应该如下所示:
http://del.icio.us/feeds/json/bob/mochikit+interpreter?jsonp=delicious_callbacks%5B12345%5D
delicious_callbacks[12345]([{
"u": "http://mochikit.com/examples/interpreter/index.html",
"d": "Interpreter - JavaScript Interactive Interpreter",
"t": [
"mochikit","webdev","tool","tools",
"javascript","interactive","interpreter","repl"
]
}])
可见,由于使用圆括号括住了返回的数据,这就相当于把一个JSONP请求转化成了一次函数调用,或者得到了一个纯粹的JSON直接量。服务器所要配合做的,就是在JSON数据的开头添加一小段文本(即回调函数的名称。——译者注)并将JSON数据放在括号中!
当然,接下来最好是使用Mochikit、Dojo等框架来抽象JSONP,从而让自己省去动手编写DOM以插入script标签的麻烦。
没错,JSONP只是解决了标准化的问题。假如远程主机想通过script标签向页面中注入恶意代码,而不是返回JSON数据,那么页面安全可能会随时受到威胁。不过,一旦实现了JSONP,那么对开发人员来说肯定是一件省时省力的大好事,在此基础上各种一般化的抽象、教程及文档也会应运而生的。
注:缩写词 JSONP 由 Bob Ippolito 在一篇名为 “Remote JSON – JSONP” 的文章中提出。但许多支持以 JSONP 技术实现跨域通信的厂商没有称其为 JSONP。例如,雅虎公司就称这种技术为 “JSON with callbacks”。另外,原文发表于2005年12月5日。
为之漫笔(李松峰),本博客专注于Web前后端技术、移动平台开发技术、交互设计和技术翻译。声明一下,因为时常需要外出审稿,而且基本不带笔记本,所以有时可能会迟一点回复大家的留言。
中秋好。
怎么把我的链接去掉了呢?
给我做个链接可以吗???
非常感谢!!
我的EMAIL:[email protected]
大概是说通过script的src来实现跨域,通过经编码的json在url中传递数据?
是不是说页面上的js生产带有不同参数的jsonp,通过src传递给服务端,服务端根据该jsonp返回相应数据?有点不太明白,能否提供一个实例?谢谢
@vampire
你的理解是对的,看来我的翻译你能看明白,呵呵。使用JSONP技术时,一般是由JS在客户端页面中动态插入script标签,将其src属性设置为带参数的URL。当页面加载时,前述URL会将参数通过GET请求发送到相应服务器端应用程序(由URL表示),服务器根据参数返回数据——注意,这个数据格式是JSON,并且(注意)被包含在一个函数调用中,例如:callback({json_data})。这样,在客户端页面中存在预定义的callback(data)函数的定义时,服务器返回的函数调用就会立即执行,由客户端的函数对数据进行操作。
实际的例子有很多,如Yahoo Search、Google Base、Flickr Search、Amazon Search等等。要学习和使用这些站点提供的支持JSONP的API,一般要注意两点:一是有的站点要求注册密钥(使用时必须放到参数中),二是要注意参数的使用方法。例如,有的API要求使用预定义的回调函数,而有的API则允许使用者自己定义回调函数。
下面就是向Flickr Search请求JSONP响应的URL,其中使用了预定义的回调函数jsonFlickrApi(参数中不必给出):
http://api.flickr.com/services/rest/
?method=flickr.photos.search
&api_key=85618ad7d326d8ef93c6bee9ed32706f
&per_page=5&format=json&text=china
下面这个URL发送到Google Base,它允许开发人员使用自己定义的回调函数:
http://www.google.com/base/feeds/snippets
?q=jquery
&alt=json-in-script
&callback=customCallback
把前面的URL放到浏览器地址栏中,回车,即可看到结果。
管理员能回复下吗?
不可以的话也说声。
有劳了。
给你回的邮件没收到吗?最近,网站空间提供商要求我们必须删除可能侵犯知识产权的链接。所以,就全都删除了。
@admin:嗯 明白了 实际上跟本地调用函数差不多 只不过通过src提交了请求并得到了具体数据参数 很聪明的办法 非常感谢
去年就开始看你的博客了 只是来的很少 会继续关注你的博客:-)
function customCallback(obj){
for(var i in obj)
alert(i+”:”+obj[i]);
}
应该是类似这样
Javascript 使用 CSS 异步跨域获取数据:
http://www.gracecode.com/Archive/Display/2469
在我的blog页面http://www.hadoop.org.cn/web/jsonp/上有实现思路和简单代码.
JSONP的安全性值得思考.远程主机搞点恶意代码,用户可不知道你访问的是别人的主机.也只能怪罪于现在访问的站点了.
[...] – JSONP的起源 saved by geeked2009-03-21 – 《尻 [...]
[...] 我们看到在使用jquery ajax时,指定数据类型为jsonp,jsonp是一种可跨域访问的协议,我对其也不是非常清楚,可以在这里了解一下。另外 CSS9.NET 也计划在后面的文章中讲解json的相关知识,敬请关注。 [...]
[...] jsonp(JSON with Padding): 简单点说,异步请求跨域的服务器端时,不是直接返回数据,而是返回一个js方法,把数据作为参数传过来。这需要服务器端稍作修改,如果只是跨域传递数据(而不是DOM操作),个人认为这种方式是最好的。参考内容:使用 JSONP 实现跨域通信 [...]
感觉楼主很用心,会常来看你的文章和博客的。
Excellently written article, if only all blogger offered the same level of content as you, the internet would be a much better place. Please keep it up!
jsonp大概知道有这么回事,一直用不到,看您这篇就清晰多了。
Hello, Nice work! This is my first time i visit here. I discovered so numerous fascinating stuff in your website.
I am experiencing a situation with your rss feed . Don’t know why I am not able to subscribe to it. Is there anybody getting an identical rss problem? Anybody who is aware of kindly respond. Thanks
Nice post. I study one thing on totally different blogs everyday. It’s going to always be stimulating to read content from different writers and observe a little bit something from their blog.
Thank you for all of the effort on this blog
Youre so cool! I dont suppose Ive read anything like this before. So nice to find somebody with some original thoughts on this subject.
I was very pleased to find this website. I wanted to thank you for your time for this wonderful post!! I definitely enjoy reading it and I have you bookmarked to check out new stuff you blog post.
This really answered my problem, thank you!
Your place is valueble for me. Thanks!…
This is the best web blog I have read.
Good day I am so grateful I found your site, I really found you by mistake, while I was researching on Aol for something else, Anyhow I am here now and would just like to say many thanks for a remarkable post and a all round thrilling blog (I also love the theme/design), I don’t have time to read it all at the minute but I have saved it and also included your RSS feeds, so when I have time I will be back to read a lot more, Please do keep up the excellent job.
This was a great post, thanks for the info.
Hardly ever do I encounter a weblog that’s both educated and entertaining, and let me let you know, you have hit the nail on the head. Your thought is excellent; the issue is something that not sufficient individuals are speaking intelligently about. I am very happy that I stumbled across this in my quest for info relating to this.
I definitely enjoy every little bit of it and I have bookmarked your blog.
Thanks for spending the time to discuss this, I feel strongly about it and love reading more on this topic.
It’s hard to find knowledgeable people on this topic, but you sound like you know what you’re talking about! Thanks
I really relate to that post. Thanks for the info.
Wow, I enjoyed your neat post.
Aw, this was a very nice post. In thought I want to write like this – taking time and actual effort to make a very good article is very rare…
Thanks for spending the time to discuss this, I feel strongly about it and love studying more on this topic. If attainable, as you develop into an expert, would you mind updating your weblog with more details?
It’s hard to find knowledgeable people on this topic, but you sound like you know what you’re talking about! Thanks
His times using the Bears started to be numbered using the signing of Marion Barber, and any attempts to business him went nowhere. but do not exercise using the team. He is anticipated to participate in Wednesday’s workout and be available when Arizona opens its time period Sunday at house against the Carolina Panthers.<yangchengbin/201111
Thanks for your opinion. discount handbags I totally like with it.I like cheap designer handbags as well and someone is looking for cheap handbags People usually prefer fake designer handbags, especially when they visit some handbags outlet. In some areas,people like to wholesale clothing. They will find some store doing very cheap or discounted Chanel Handbags outlet. Certainly, is a good way to earn money. designer handbags outlet
Hi, the article is so wonderful, I am interested in it. I will pay attention to your articles.
Thank you for your articles
They will find some store doing very cheap or discounted Chanel Handbags outlet.
Full exercise of the thigh muscles, exercise, and to exercise Christian Louboutin Pumps for sale their legs, and then full massage to be able to gradually improve the sturdy legs of trouble.
NFL spokesman Greg Aiello acknowledged the discussions using the Colts greater compared to weekend. “The team completely understood the problems and committed to addressing them,” Aiello mentioned in an electric mail toward the connected Press.”We have been informed last evening of the choice reached by the team and Mr. Tressel. We think it is appropriate.”
In a statement, Polian mentioned that “questions have been raised with respect toward the equity of his appointment as opposed to suspensions getting serves this season by present and previous Ohio State players.” yangchengbin/201111
is a good article for us ,i have been find everywhere for this kind of point ,All Moncler products are produced by Original Brand from Manufacturer.yangchengbin/201112
good arctile , thanks for sharing it and please keep doing this good job .
good post , i like it , thanks for sharing it . have a nice day .