JSON和JSONP的区别

来源:互联网 发布:证件制作软件手机版 编辑:程序博客网 时间:2024/05/23 11:48

 简单的说JSON是一种数据交换格式,而JSONP是一种非官方跨域数据交互协议。JSON是“暗号”,而JSONP则是接头方式。一个是描述信息的格式,一个是信息传递双方约定的方法。

一、什么是JSON

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。 它基于 JavaScript Programming Language , Standard ECMA-262 3rd Edition - December 1999 的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。 这些特性使JSON成为理想的数据交换语言。

JSON建构于两种结构:

  • “名称/值”对的集合(A collection of name/value pairs)。不同的语言中,它被理解为对象(object),纪录(record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(keyed list),或者关联数组 (associative array)。

  • 值的有序列表(An ordered list of values)。在大部分语言中,它被理解为数组(array)。

    这些都是常见的数据结构。事实上大部分现代计算机语言都以某种形式支持它们。这使得一种数据格式在同样基于这些结构的编程语言之间交换成为可能。

二、什么是JSONP?

JSONP( JSON with Padding )是资料格式 JSON 的一种“使用模式”,可以让网页从别的网域要资料。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com 的服务器沟通,而 HTML 的 <script> 元素是一个例外。利用<script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。用 JSONP 抓到的资料并不是 JSON,而是任意的 JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析。

为了理解这种模式的原理,先想像有一个回传 JSON 文件的 URL,而 JavaScript 程式可以用 XMLHttpRequest 跟这个 URL 要资料。假设我们的 URL 是http://server2.example.com/RetrieveUser?UserId=xxx 。假设小明的 UserId 是 1823,且当浏览器透过 URL 传小明的 UserId,也就是抓取http://server2.example.com/RetrieveUser?UserId=1823 ,得到:

{"Name": "小明", "Id" : 1823, "Rank": 7}

这个 JSON 资料可能是依据传过去 URL 的查询参数动态产生的。

这个时候,把 <script> 元素的 src 属性设成一个回传 JSON 的 URL 是可以想像的,这也代表从 HTML 页面透过 script 元素抓取 JSON 是可能的。

然而,一份 JSON 文件并不是一个 JavaScript 程式。为了让浏览器可以在 <script> 元素执行,从 src 里 URL 回传的必须是可执行的 JavaScript。在 JSONP 的使用模式里,该 URL 回传的是由函数呼叫包起来的动态生成 JSON,这就是JSONP 的“填充(padding)”或是“前辍(prefix)”的由来。

惯例上浏览器提供回调函数的名称当作送至服务器的请求中命名查询参数的一部份,例如:

<script type="text/javascript" src="http://server2.example.com/RetrieveUser?UserId=1823&jsonp=parseResponse"> </script>

服务器会在传给浏览器前将 JSON 数据填充到回调函数(parseResponse)中。浏览器得到的回应已不是单纯的资料叙述而是一个脚本。在本例中,浏览器得到的是:

parseResponse({"Name": "Cheeso", "Id" : 1823, "Rank": 7})

虽然这个填充(前辍)“通常”是浏览器执行背景中定义的某个回调函数,它也可以是变量赋值、if 叙述或者是其他 JavaScript 叙述。JSONP 要求(也就是使用 JSONP 模式的请求)的回应不是 JSON 也不被当作 JSON 解析——回传内容可以是任意的运算式,甚至不需要有任何的 JSON,不过惯例上填充部份还是会触发函数调用的一小段 JavaScript 片段,而这个函数呼叫是作用在 JSON 格式的资料上的。

另一种说法—典型的 JSONP 就是把既有的 JSON API 用函数呼叫包起来以达到跨域存取的解法。为了要启动一个 JSONP 呼叫(或者说,使用这个模式),你需要一个 script 元素。因此,浏览器必须为每一个 JSONP 要求加(或是重用)一个新的、有所需 src 值的 <script> 元素到 HTML DOM 里—或者说是“注入”这个元素。浏览器执行该元素,抓取 src 里的 URL,并执行回传的 JSON。也因为这样,JSON 被称作是一种“让使用者利用 script 元素注入的方式绕开同源策略”的方法。

使用远端网站的 script 标签会让远端网站得以注入任何的内容至网站里。如果远端的网站有 JavaScript 注入漏洞,原来的网站也会受到影响.现在有一个正在进行计划在定义所谓的 JSON-P 严格安全子集,使浏览器可以对 MIME 类别是“application/json-p”请求做强制处理。如果回应不能被解析为严格的 JSON-P,浏览器可以丢出一个错误或忽略整个回应。

粗略的 JSONP 部署很容易受到跨网站的伪造要求(CSRF/XSRF)的攻击。因为 HTML <script> 标签在浏览器里不遵守同源策略,恶意网页可以要求并取得属于其他网站的 JSON 资料。当使用者正登入那个其他网站时,上述状况使得该恶意网站得以在恶意网站的环境下操作该 JSON 资料,可能泄漏使用者的密码或是其他敏感资料。

只有在该 JSON 资料含有不该泄漏给第三方的隐密资料,且服务器仅靠浏览器的同源策略阻挡不正常要求的时候这才会是问题。若服务器自己决定要求的专有性,并只在要求正常的情况下输出资料则没有问题。只靠 Cookie 并不够决定要求是合法的,这很容易受到跨网站的伪造要求攻击。


0 0