什么是 JSONP,为什么要创建它?
问:
我了解 JSON,但不了解 JSONP。 Wikipedia’s document on JSON 是(曾经)JSONP 的热门搜索结果。它是这样说的:
JSONP 或“带填充的 JSON”是 JSON 扩展,其中前缀被指定为调用本身的输入参数。
嗯?什么电话?这对我来说没有任何意义。 JSON 是一种数据格式。没有电话。
2nd search result 来自某个名叫 Remy 的人,他写了以下关于 JSONP 的文章:
JSONP 是脚本标签注入,将来自服务器的响应传递给用户指定的函数。
我可以理解这一点,但它仍然没有任何意义。
那么什么是 JSONP?为什么创建它(它解决了什么问题)?我为什么要使用它?
附录:我刚刚在 Wikipedia 上创建了 a new page for JSONP;根据 jvenema 的回答,它现在对 JSONP 进行了清晰而全面的描述。
答1:
打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!
其实也不是很复杂…
假设您在域 example.com 上,并且想要向域 example.net 发出请求。为此,您需要跨域边界,这是大多数浏览器领域中的no-no。
绕过此限制的一项是
输入 JSONP。当您向启用 JSONP 的服务器发出请求时,您会传递一个特殊参数,该参数会告诉服务器一些关于您的页面的信息。这样,服务器就能够以您的页面可以处理的方式很好地包装其响应。
例如,假设服务器需要一个名为 callback 的参数来启用其 JSONP 功能。那么您的请求将如下所示:
http://www.example.net/sample.aspx?callback=mycallback
如果没有 JSONP,这可能会返回一些基本的 JavaScript 对象,如下所示:
{
foo: 'bar' }
然而,使用 JSONP,当服务器接收到“回调”参数时,它会稍微不同地包装结果,返回如下内容:
mycallback({
foo: 'bar' });
如您所见,它现在将调用您指定的方法。因此,在您的页面中,您定义了回调函数:
mycallback = function(data){
alert(data.foo);
};
现在,当脚本被加载时,它将被评估,并且你的函数将被执行。瞧,跨域请求!
还值得注意的是 JSONP 的一个主要问题:您失去了对请求的大量控制。例如,没有“好”的方式来获取正确的故障代码。结果,您最终使用计时器来监视请求等,这总是有点可疑。 JSONRequest 的提议是允许跨域脚本、维护安全性和允许适当控制请求的一个很好的解决方案。
如今(2015 年),与 JSONRequest 相比,CORS 是推荐的方法。 JSONP 对于较旧的浏览器支持仍然有用,但考虑到安全隐患,除非您别无选择,否则 CORS 是更好的选择。
请注意,使用 JSONP 有一些安全隐患。由于 JSONP 是真正的 javascript,它可以做 javascript 可以做的所有事情,因此您需要信任 JSONP 数据的提供者。我在这里写了一篇关于它的博客文章:erlend.oftedal.no/blog/?blogid=97
JSONP 中是否真的存在
不,它没有。如果您信任它来提供 javascript,同样的事情也适用于 JSONP。
值得注意的是,您可以通过更改数据的返回方式来稍微提高安全性。如果您以真正的 JSON 格式返回脚本,例如 mycallback('{"foo":"bar"}')(注意参数现在是字符串),那么您可以自己手动解析数据以“清理”它之前评估。
CURL 是服务器端解决方案,而不是客户端。它们有两个不同的目的。
答2:
huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。
JSONP 确实是克服 XMLHttpRequest 同域策略的简单技巧。 (如您所知,不能将 AJAX (XMLHttpRequest) 请求发送到不同的域。)
所以 - 我们必须使用脚本 HTML 标签而不是使用 XMLHttpRequest,这些标签通常用于加载 js 文件,以便 js 从另一个域获取数据。听起来怪怪的?
事实是 - 原来脚本标签可以以类似于 XMLHttpRequest 的方式使用!看一下这个:
script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'http://www.someWebApiServer.com/some-data';
加载数据后,您最终会得到一个如下所示的脚本段:
{
['some string 1', 'some data', 'whatever data']}
然而这有点不方便,因为我们必须从脚本标签中获取这个数组。所以 JSONP 的创建者决定这样做会更好(而且确实如此):
script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'http://www.someWebApiServer.com/some-data?callback=my_callback';
注意到那边的 my_callback 函数了吗?所以 - 当 JSONP 服务器收到您的请求并找到回调参数时 - 它不会返回普通的 js 数组,而是返回:
my_callback({
['some string 1', 'some data', 'whatever data']});
看看利润在哪里:现在我们得到自动回调(my_callback),一旦我们得到数据就会触发。这就是关于 JSONP 的全部知识:它是一个回调和脚本标签。
注意:这些是 JSONP 使用的简单示例,这些不是生产就绪脚本。
基本 JavaScript 示例(使用 JSONP 的简单 Twitter 提要)
function myCallback(dataWeGotViaJsonp){
var text = '';
var len = dataWeGotViaJsonp.length;
for(var i=0;i<len;i++){
twitterEntry = dataWeGotViaJsonp[i];
text += '<p><img src = "' + twitterEntry.user.profile_image_url_https +'"/>' + twitterEntry['text'] + '</p>'
}
document.getElementById('twitterFeed').innerHTML = text;
}
基本 jQuery 示例(使用 JSONP 的简单 Twitter 提要)
$(document).ready(function(){
$.ajax({
url: 'http://twitter.com/status/user_timeline/padraicb.json?count=10',
dataType: 'jsonp',
success: function(dataWeGotViaJsonp){
var text = '';
var len = dataWeGotViaJsonp.length;
for(var i=0;i<len;i++){
twitterEntry = dataWeGotViaJsonp[i];
text += '<p><img src = "' + twitterEntry.user.profile_image_url_https +'"/>' + twitterEntry['text'] + '</p>'
}
$('#twitterFeed').html(text);
}
});
})
JSONP 代表 JSON with Padding。 (命名非常糟糕的技术,因为它实际上与大多数人认为的“填充”无关。)
感谢脚本标签的解释。我无法弄清楚 JSONP 是如何绕过跨域安全策略的。在解释之后,我觉得有点愚蠢,没有抓住重点......
这是对 jvenema 答案的一个很好的补充答案 - 我不明白为什么回调是必要的,直到您指出 json 数据否则必须通过脚本元素访问。
感谢您提供如此清晰的解释。我希望我的大学教科书是像你这样的人写的:)
很好的解释,而不是前一个。当然-您的摘录“您通常用来加载 js 文件的那些,以便 js 从另一个域获取数据。听起来很奇怪?”也让我大开眼界。示例代码非常出色。
我更喜欢这个带有具体例子的解释,而不是公认的答案!谢谢!
答3:
huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。
JSONP 通过构造“脚本”元素(在 HTML 标记中或通过 JavaScript 插入 DOM)来工作,该元素请求远程数据服务位置。响应是加载到浏览器的 javascript,带有预定义函数的名称以及传递的参数,即请求的 JSON 数据。当脚本执行时,该函数与 JSON 数据一起被调用,允许请求页面接收和处理数据。
进一步阅读访问: https://blogs.sap.com/2013/07/15/secret-behind-jsonp/
客户端代码片段
AvLabz - CORS : The Secrets Behind JSONP
Send Request to Server
"use strict";
//Construct the script tag at Runtime
function requestServerCall(url) {
var head = document.head;
var script = document.createElement("script");
script.setAttribute("src", url);
head.appendChild(script);
head.removeChild(script);
}
//Predefined callback function
function jsonpCallback(data) {
alert(data.message); // Response data from the server
}
//Reference to the input field
var username = document.getElementById("username");
//Send Request to Server
function sendRequest() {
// Edit with your Web Service URL
requestServerCall("http://localhost/PHP_Series/CORS/myService.php?callback=jsonpCallback&message="+username.value+"");
}
服务器端的一段 PHP 代码
打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!
顶部的链接现在只有 404
该链接的内容现在可在 http://scn.sap.com/community/developer-center/front-end/blog/2013/07/15/secret-behind-jsonp 获得。
答4:
huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。
因为您可以要求服务器为返回的 JSON 对象添加前缀。例如
function_prefix(json_object);
为了让浏览器eval将 JSON 字符串作为表达式“内联”。这个技巧使服务器可以直接在客户端浏览器中“注入”javascript代码,并且绕过“同源”限制。
也就是说,可以实现跨域的数据交换。
通常,XMLHttpRequest 不允许直接进行跨域数据交换(需要通过同一域中的服务器),而:
还没有评论,来说两句吧...