JSONP(JSON with Padding)是数据格式JSON的一种“使用模式”,可以让网页从别的网域要数据。另一个解决这个问题的新方法是跨来源资源共享。
由于同源策略,一般来说位于server1.example.com的网页无法与 server2.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,33);">"Rank"7}
这个JSON数据可能是依据传过去URL的查询参数动态产生的。
这个时候,把<script>元素的src属性设成一个回传JSON的URL是可以想像的,这也代表从HTML页面通过script元素抓取 JSON是可能的。
然而,一份JSON文件并不是一个JavaScript程序。为了让浏览器可以在<script>元素运行,从src里URL 回传的必须是可执行的JavaScript。在JSONP的使用模式里,该URL回传的是由函数调用包起来的动态生成JSON,这就是JSONP的“填充(padding)”或是“前辍(prefix)”的由来。
惯例上浏览器提供回调函数的名称当作送至服务器的请求中命名查询参数的一部分,例如:
服务器会在传给浏览器前将JSON数据填充到回调函数(parseResponse)中。浏览器得到的回应已不是单纯的数据叙述而是一个脚本。在本例中,浏览器得到的是:
填充[虽然这个填充(前辍)“通常”是浏览器运行背景中定义的某个回调函数,它也可以是变量赋值、if叙述或者是其他JavaScript叙述。JSONP要求(也就是使用JSONP模式的请求)的回应不是JSON也不被当作JSON解析——回传内容可以是任意的表达式,甚至不需要有任何的JSON,不过惯例上填充部分还是会触发函数调用的一小段JavaScript片段,而这个函数调用是作用在JSON格式的数据上的。
另一种说法—典型的JSONP就是把既有的JSON API用函数调用包起来以达到跨域访问的解法。
Script元素“注入”[为了要引导一个JSONP调用(或者说,使用这个模式),你需要一个script 元素。因此,浏览器必须为每一个JSONP要求加(或是重用)一个新的、有所需 src值的<script>元素到HTML DOM里—或者说是“注入”这个元素。浏览器运行该元素,抓取src里的URL,并运行回传的 JavaScript。
也因为这样,JSONP被称作是一种“让用户利用script元素注入的方式绕开同源策略”的方法。
安全问题[使用远程网站的script标签会让远程网站得以注入任何的内容至网站里。如果远程的网站有JavaScript注入漏洞,原来的网站也会受到影响。
现在有一个正在进行项目在定义所谓的JSON-P严格安全子集,使浏览器可以对MIME类别是“application/json-p”请求做强制处理。如果回应不能被解析为严格的JSON-P,浏览器可以丢出一个错误或忽略整个回应。
跨站请求伪造[粗略的JSONP部署很容易受到跨站请求伪造(CSRF/XSRF)的攻击[1]。因为HTML<script>标签在浏览器里不遵守同源策略,恶意网页可以要求并获取属于其他网站的JSON数据。当用户正登录那个其他网站时,上述状况使得该恶意网站得以在恶意网站的环境下操作该JSON数据,可能泄漏用户的密码或是其他敏感数据。
只有在该JSON数据含有不该泄漏给第三方的隐密数据,且服务器仅靠浏览器的同源策略阻挡不正常要求的时候这才会是问题。若服务器自己决定要求的专有性,并只在要求正常的情况下输出数据则没有问题。只靠Cookie并不够决定要求是合法的,这很容易受到跨站请求伪造攻击。
也因为这样,JSONP被称作是一种“让用户利用script元素注入的方式绕开同源策略”的方法。
安全问题[使用远程网站的script标签会让远程网站得以注入任何的内容至网站里。如果远程的网站有JavaScript注入漏洞,原来的网站也会受到影响。
现在有一个正在进行项目在定义所谓的JSON-P严格安全子集,使浏览器可以对MIME类别是“application/json-p”请求做强制处理。如果回应不能被解析为严格的JSON-P,浏览器可以丢出一个错误或忽略整个回应。
跨站请求伪造[粗略的JSONP部署很容易受到跨站请求伪造(CSRF/XSRF)的攻击[1]。因为HTML<script>标签在浏览器里不遵守同源策略,恶意网页可以要求并获取属于其他网站的JSON数据。当用户正登录那个其他网站时,上述状况使得该恶意网站得以在恶意网站的环境下操作该JSON数据,可能泄漏用户的密码或是其他敏感数据。
只有在该JSON数据含有不该泄漏给第三方的隐密数据,且服务器仅靠浏览器的同源策略阻挡不正常要求的时候这才会是问题。若服务器自己决定要求的专有性,并只在要求正常的情况下输出数据则没有问题。只靠Cookie并不够决定要求是合法的,这很容易受到跨站请求伪造攻击。
只有在该JSON数据含有不该泄漏给第三方的隐密数据,且服务器仅靠浏览器的同源策略阻挡不正常要求的时候这才会是问题。若服务器自己决定要求的专有性,并只在要求正常的情况下输出数据则没有问题。只靠Cookie并不够决定要求是合法的,这很容易受到跨站请求伪造攻击。