深入了解 JSONP

最后更新:
阅读次数:

JSONP(JSON with Padding)wiki 是数据格式 JSON 的一种“使用模式”,可以让网页从别的源获取数据。

  • 核心原理:由于 HTML 的 <script> 标签在浏览器里不遵守同源策略,所以可以设置该元素的 src 属性并通过为 URL 添加一个查询(?callback=aCallbackFunction)来实现跨源通信

上面的原理通俗点解释就是:本地页面通过动态添加 script 标签来调用服务器提供的 JavaScript 脚本,从而实现跨源通信。

并且,看到上面为 URL 添加查询,瞬间想到了 GET 请求。而事实上,JSONP 获取数据只能通过 GET 请求获得。

  • 事实上,带有 src 属性的 HTML 标签(例如 <script><img><iframe>)都不遵守同源策略。

  • 通过 JSONP 抓到的数据并不是 JSON,而是任意的 JavaScript 代码,用 JavaScript 解释器运行而不是用 JSON 解析器解析。

下面举一个例子,为了方便,我在本地服务器(Wamp Server)上进行测试。

// 当前页面:http://blog.percymong.com/
// 以下代码复制粘贴于浏览器控制端下运行

function addScriptTag(src) {
var script = document.createElement("script");
script.src = src;
document.body.appendChild(script);
}

// 点击页面 body 触发回调函数
document.body.onclick = function() {
addScriptTag("http://localhost:9999/test/jsonp.php?cb=whateverFunc");
};

// 编写回调函数
function whateverFunc(data) {
console.log(data);
console.log("回调函数调用成功~");
}
// 请求页面:http://localhost:9999/test/jsonp.php

<?php
$callback = $_GET['cb'];
$dataForJSONP = [1,2,3,4];

echo "$callback(".json_encode($dataForJSONP, 256).")";
?>

网上有人说,JSONP 是 Ajax 实现跨源的一种方式,但是这种说法没有依据。

JSONP 和 Ajax 本质上是不同的东西,JSONP 的核心是动态添加 <script> 标签来调用服务器提供的 javascript 脚本,而 ajax 的核心是通过 XmlHttpRequest 获取非本页内容。

JSONP 曾经在开发人员之间极为流行,主要原因是它非常简单易用。但是它也有不足之处:一是安全系数不够高,如果请求的域不安全,则请求的内容可能会夹杂有恶意代码。二是无法确定 JSONP 请求是否成功。

对于第二个缺点,现在已经可以得到解决:使用 onerror 事件处理程序检错。GlobalEventHandlers.onerror

// 各大浏览器亲测有效
function addScript(src) {
var script = document.createElement("script");
script.src = src;
script.onerror = function() {
console.log("script failed load");
};
document.body.appendChild(script);
}
addScript("http://www.percymong.com/neverGetMe.js");

参考资料