什么是 JSONP,为什么要创建它?

心已赠人 2024-03-30 01:37 240阅读 0赞

问:

我了解 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 功能。那么您的请求将如下所示:

  1. http://www.example.net/sample.aspx?callback=mycallback

如果没有 JSONP,这可能会返回一些基本的 JavaScript 对象,如下所示:

  1. {
  2. foo: 'bar' }

然而,使用 JSONP,当服务器接收到“回调”参数时,它会稍微不同地包装结果,返回如下内容:

  1. mycallback({
  2. foo: 'bar' });

如您所见,它现在将调用您指定的方法。因此,在您的页面中,您定义了回调函数:

  1. mycallback = function(data){
  2. alert(data.foo);
  3. };

现在,当脚本被加载时,它将被评估,并且你的函数将被执行。瞧,跨域请求!

还值得注意的是 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 的方式使用!看一下这个:

  1. script = document.createElement('script');
  2. script.type = 'text/javascript';
  3. script.src = 'http://www.someWebApiServer.com/some-data';

加载数据后,您最终会得到一个如下所示的脚本段:

  1. {
  2. ['some string 1', 'some data', 'whatever data']}

然而这有点不方便,因为我们必须从脚本标签中获取这个数组。所以 JSONP 的创建者决定这样做会更好(而且确实如此):

  1. script = document.createElement('script');
  2. script.type = 'text/javascript';
  3. script.src = 'http://www.someWebApiServer.com/some-data?callback=my_callback';

注意到那边的 my_callback 函数了吗?所以 - 当 JSONP 服务器收到您的请求并找到回调参数时 - 它不会返回普通的 js 数组,而是返回:

  1. my_callback({
  2. ['some string 1', 'some data', 'whatever data']});

看看利润在哪里:现在我们得到自动回调(my_callback),一旦我们得到数据就会触发。这就是关于 JSONP 的全部知识:它是一个回调和脚本标签。

注意:这些是 JSONP 使用的简单示例,这些不是生产就绪脚本。

基本 JavaScript 示例(使用 JSONP 的简单 Twitter 提要)

  1. function myCallback(dataWeGotViaJsonp){
  2. var text = '';
  3. var len = dataWeGotViaJsonp.length;
  4. for(var i=0;i<len;i++){
  5. twitterEntry = dataWeGotViaJsonp[i];
  6. text += '<p><img src = "' + twitterEntry.user.profile_image_url_https +'"/>' + twitterEntry['text'] + '</p>'
  7. }
  8. document.getElementById('twitterFeed').innerHTML = text;
  9. }

基本 jQuery 示例(使用 JSONP 的简单 Twitter 提要)

  1. $(document).ready(function(){
  2. $.ajax({
  3. url: 'http://twitter.com/status/user_timeline/padraicb.json?count=10',
  4. dataType: 'jsonp',
  5. success: function(dataWeGotViaJsonp){
  6. var text = '';
  7. var len = dataWeGotViaJsonp.length;
  8. for(var i=0;i<len;i++){
  9. twitterEntry = dataWeGotViaJsonp[i];
  10. text += '<p><img src = "' + twitterEntry.user.profile_image_url_https +'"/>' + twitterEntry['text'] + '</p>'
  11. }
  12. $('#twitterFeed').html(text);
  13. }
  14. });
  15. })

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/

客户端代码片段

  1. AvLabz - CORS : The Secrets Behind JSONP
  2. Send Request to Server
  3. "use strict";
  4. //Construct the script tag at Runtime
  5. function requestServerCall(url) {
  6. var head = document.head;
  7. var script = document.createElement("script");
  8. script.setAttribute("src", url);
  9. head.appendChild(script);
  10. head.removeChild(script);
  11. }
  12. //Predefined callback function
  13. function jsonpCallback(data) {
  14. alert(data.message); // Response data from the server
  15. }
  16. //Reference to the input field
  17. var username = document.getElementById("username");
  18. //Send Request to Server
  19. function sendRequest() {
  20. // Edit with your Web Service URL
  21. requestServerCall("http://localhost/PHP_Series/CORS/myService.php?callback=jsonpCallback&message="+username.value+"");
  22. }

服务器端的一段 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 不允许直接进行跨域数据交换(需要通过同一域中的服务器),而:

发表评论

表情:
评论列表 (有 0 条评论,240人围观)

还没有评论,来说两句吧...

相关阅读

    相关 什么闭包,为什么

    闭包是指有权访问另一个函数作用域内变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,创建的函数可以 访问到当前函数的局部变量。 闭包有两个常用的用途。