JSONP的一点笔记<修改中>
同源策略同源策略(Same origin policy),它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。[2] 同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。[3] 如果非同源,共有三种行为受到限制:
AJAXAsynchronous JavaScript and XML (Ajax) Ajax 允许在不干扰 Web 应用程序的显示和行为的情况下在后台进行数据检索。使用 XMLHttpRequest 函数获取数据,它是一种 API,允许客户端 JavaScript 通过 HTTP 连接到远程服务器。 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。JSON 依赖于 JavaScript 开发人员,因为它是 JavaScript 对象的字符串表示。例如,假设有一个含两个属性的 ticker 对象:symbol 和 price。这是在 JavaScript 中定义 ticker 对象的方式:
并且这是它的 JSON 表示方式: 有关 JSON 和将其作为数据内部交换格式的信息。清单 1 定义了一个 JavaScript 函数,调用该函数时会显示 IBM 的股价。 清单 1. 定义 showPrice 函数 function showPrice(data) { alert("Symbol: " + data.symbol + ",Price: " + data.price); } 可以将 JSON 数据作为参数传递,以调用该函数: showPrice({symbol: 'IBM',price: 91.42}); // alerts: Symbol: IBM,Price: 91.42 现在准备将这两个步骤包含到 Web 页面,如清单 2 所示。 <script type="text/javascript"> function showPrice(data) { alert("Symbol: " + data.symbol + ",Price: " + data.price); } </script> <script type="text/javascript">showPrice({symbol: 'IBM',price: 91.42});</script> 加载页面后,应该看如图 1 所示的警告 showPrice({symbol: 'IBM',price: 91.42}); 现在改变 Web 页面中的脚本,使其和清单 3 一样。 <script type="text/javascript"> // This is our function to be called with JSON data function showPrice(data) { alert("Symbol: " + data.symbol + ",Price: " + data.price); } var url = “ticker.js”; // URL of the external script // this shows dynamic script insertion var script = document.createElement('script'); script.setAttribute('src',url); // load the script document.getElementsByTagName('head')[0].appendChild(script); </script> 在清单 3 所示的例子中,动态插入的 JavaScript 代码位于 ticker.js 文件中,它将真正的 JSON 数据作为参数调用 showPrice()函数。 JSON语法JSON 语法是 JavaScript 对象表示法语法的子集。 // 描述一个人 var person = { "Name": "Bob","Age": 32,"Company": "IBM","Engineer": true } // 获取这个人的信息 var personAge = person.Age; // 描述几个人 var members = [ { "Name": "Bob","Engineer": true },{ "Name": "John","Age": 20,"Company": "Oracle","Engineer": false },{ "Name": "Henry","Age": 45,"Company": "Microsoft","Engineer": false } ] // 读取其中John的公司名称 var johnsCompany = members[1].Company; // 描述一次会议 var conference = { "Conference": "Future Marketing","Date": "2012-6-1","Address": "Beijing","Members": [ { "Name": "Bob","Engineer": true },{ "Name": "John","Engineer": false },{ "Name": "Henry","Engineer": false } ] } // 读取参会者Henry是否工程师 var henryIsAnEngineer = conference.Members[2].Engineer; JSONP是JSON with Padding的略称。它是一个非官方的跨域数据交互协议协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。[4] JSONP是怎么产生的:通俗的阐释: 1.Ajax直接请求普通文件存在跨域无权限访问的问题,无论是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准; 2.Web页面上调用js文件时则不受是否跨域的影响(凡是拥有"src"这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>); 3.基于上述,如果想通过纯web端(ActiveX控件、服务端代理、HTML5之Websocket等方式暂不考虑)跨域访问数据存在这样一种可能:即在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理; 4.恰巧,JSON作为纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据; 5.于是,解决方案:web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件(一般以JSON为后缀),显而易见,服务器之所以要动态生成JSON文件,目的就在于把客户端需要的数据装入进去。 6.客户端在对JSON文件调用成功之后,也就获得了自己所需的数据,剩下的就是按照自己需求进行处理和展现了,这种获取远程数据的方式看起来非常像AJAX,但其实并不一样。 7.为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。[6] JSONP是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,老式浏览器全部支持,服务器改造非常小。 在“跨域”的问题上,我们发现src 属性并没有受到相关的限制,比如 img / script 等。 JSONP的基本思想是,网页通过添加一个<script>标签,设置这个script标签的src属性用于向服务器请求JSON数据 ,src属性的查询字符串一定要加一个callback函数,用来指定回调函数的名字 。而这个函数是在资源加载之前就已经在前端定义好的,这个函数接受一个参数并利用这个参数做一些事情。向服务器请求后,服务器会将JSON数据放在一个指定名字的回调函数里作为其参数传回来。这时,因为函数已经在前端定义好了,所以会直接调用。 首先,网页动态插入<script>元素,由它向跨源网址发出请求。 function addScriptTag(src) { var script = document.createElement('script'); script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script); } window.onload = function () { addScriptTag('http://example.com/ip?callback=foo');//请求服务器数据并规定回调函数为foo } function foo(data) { console.log('Your public IP address is: ' + data.ip); }; 上面代码通过动态添加 foo({ "ip": "8.8.8.8" }); 由于 jQuery对JSONP的实现jQuery 拥有对 JSONP 回调的本地支持。如果指定了 JSONP 回调,就可以加载位于另一个域的 JSON 数据,回调的语法为:url?callback=?。 jQuery.getJSON(url+"&callback=?",function(data) { alert("Symbol: " + data.symbol + ",Price: " + data.price); }); 为此,jQuery 将一个全局函数附加到插入脚本时需要调用的窗口对象。另外,jQuery 也能优化非跨域调用。如果向同一个域发出请求,jQuery 就将其转化为普通 Ajax 请求。[5] 使用 JSONP 支持的示例服务在上一个例子中,使用了静态文件(ticker.js)将 JavaScript 动态插入到 Web 页面中。尽管返回了 JSONP 回复,但它不允许您在 URL 中定义回调函数名。这不是 JSONP 服务。因此,如何才能将其转换为真正的 JSONP 服务呢?可使用的方法很多。这里我们将分别使用 PHP 和 Java 展示两个示例。 http://www.yourdomain.com/jsonp/ticker?symbol=IBM&callback=showPrice 在这种情况下,symbol 是表示请求 ticker symbol 的请求参数,而 callback 是 Web 应用程序的回调函数的名称。使用清单 5 所示的代码可以通过 jQuery 的 JSONP 支持调用该服务。 jQuery.getJSON("http://www.yourdomain.com/jsonp/ticker?symbol=IBM&callback=?",Price: " + data.price); }); 注意,我们使用 ? 作为回调函数名,而非真实的函数名。因为 jQuery 会用生成的函数名替换 ?。所以您不用定义类似于 showPrice() 的函数。 现成的 JSONP 服务Digg API:来自 Digg 的头条新闻: http://services.digg.com/stories/top?appkey=http%3A%2F%2Fmashup.com&type=javascript &callback=? Geonames API:邮编的位置信息: http://www.geonames.org/postalCodeLookupJSON?postalcode=10504&country=US&callback=? Flickr API:来自 Flickr 的最新猫图片: http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any &format=json&jsoncallback=? 使用$.ajax方法来实现http://api.jquery.com/jQuery.... CORS(Cross-Origin Resource Sharing ) Nginx反向代理跨域用nginx的反向代理机制解决前端跨域问题 索引:1.浏览器同源政策及其规避方法--阮一峰 参见:1.Web开发中跨域的几种解决方案 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |