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

2020/09/15 03:01 · javascript ·  · 0评论

我了解JSON,但不了解JSONP。Wikipedia上有关JSON的文档是JSONP的最高搜索结果。它说:

JSONP或“带填充的JSON”是JSON扩展,其中将前缀指定为调用本身的输入参数。

??什么电话 这对我来说毫无意义。JSON是一种数据格式。没有电话

第二个搜索结果是由某些人叫雷米,谁写的这个约JSONP:

JSONP是脚本标记注入,它将来自服务器的响应传递到用户指定的函数。

我可以理解,但这仍然没有任何意义。


那么什么是JSONP?为什么创建它(它解决了什么问题)?我为什么要使用它?


附录:我刚刚在Wikipedia 上为JSONP创建了一个新页面根据jvenema的回答,它现在对JSONP有了清晰而透彻的描述

实际上并不太复杂...

假设您正在使用域example.com,并且想向域发出请求example.net要做到这一点,你需要跨域边界,一个没有没有在大多数browserland的。

绕过此限制的一项是<script>标签。使用脚本标记时,将忽略域限制,但是在正常情况下,您实际上无法对结果任何事情,只是对脚本进行了评估。

输入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实际上是克服XMLHttpRequest相同域策略的简单技巧(您知道不能将AJAX(XMLHttpRequest)请求发送到另一个域。)

因此,为了使js从另一个域获取数据,我们不得不使用脚本 HTML标记,而不是使用XMLHttpRequest,这些标记通常是您用来加载js文件的标记。听起来怪怪的?

事实是- 可以以类似于XMLHttpRequest的方式使用脚本标签看一下这个:

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

加载数据后,您将获得一个如下所示的脚本段:

<script>
{['some string 1', 'some data', 'whatever data']}
</script>

但是,这有点不方便,因为我们必须从script标签获取此数组因此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 feed)

<html>
    <head>
    </head>
    <body>
        <div id = 'twitterFeed'></div>
        <script>
        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;
        }
        </script>
        <script type="text/javascript" src="http://twitter.com/status/user_timeline/padraicb.json?count=10&callback=myCallback"></script>
    </body>
</html>

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

<html>
    <head>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
        <script>
            $(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);
                    }
                });
            })
        </script>
    </head>
    <body>
        <div id = 'twitterFeed'></div>
    </body>
</html>

JSONP表示带有Padding的JSON(非常糟糕的技术,因为它实际上与大多数人认为的“填充”无关。)

JSONP通过构造一个“脚本”元素(以HTML标记或通过JavaScript插入DOM)来工作,该元素请求到远程数据服务位置。响应是使用预定义函数的名称以及传递的参数(即请求的JSON数据)加载到浏览器上的JavaScript。执行脚本时,该函数将与JSON数据一起调用,从而允许请求页面接收和处理数据。

有关进一步的阅读访问, 访问:https : //blogs.sap.com/2013/07/15/secret-behind-jsonp/

客户端代码段

    <!DOCTYPE html>
    <html lang="en">
    <head>
     <title>AvLabz - CORS : The Secrets Behind JSONP </title>
     <meta charset="UTF-8" />
    </head>
    <body>
      <input type="text" id="username" placeholder="Enter Your Name"/>
      <button type="submit" onclick="sendRequest()"> Send Request to Server </button>
    <script>
    "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+"");
    }    

  </script>
   </body>
   </html>

服务器端的一段PHP代码

<?php
    header("Content-Type: application/javascript");
    $callback = $_GET["callback"];
    $message = $_GET["message"]." you got a response from server yipeee!!!";
    $jsonResponse = "{\"message\":\"" . $message . "\"}";
    echo $callback . "(" . $jsonResponse . ")";
?>

因为您可以要求服务器在返回的JSON对象之前添加前缀。例如

function_prefix(json_object);

为了使浏览器eval“内联” JSON字符串作为表达式。此技巧使服务器可以直接在客户端浏览器中“注入” JavaScript代码,而绕过“相同来源”限制。

换句话说,您可以实现跨域数据交换


通常,XMLHttpRequest不允许直接跨域数据交换(需要通过同一域中的服务器),而:

<script src="some_other_domain/some_data.js&prefix=function_prefix>`可以从不同于来源的域访问数据。


同样值得注意的是:即使在尝试进行这种“欺骗”之前,应将服务器视为“受信任的”服务器,但还是可以包含对象格式可能发生变化的副作用。如果一个function_prefix(即适当的js函数)用于接收JSON对象,则该函数可以在接受/进一步处理返回的数据之前执行检查。

JSONP可以很好地解决跨域脚本错误。您可以只使用JS来使用JSONP服务,而不必在服务器端实现AJAX代理。

您可以使用b1t.co服务查看其工作方式。这是一项免费的JSONP服务,可让您缩小URL。这是用于服务的网址:

http://b1t.co/Site/api/External/MakeUrlWithGet?callback=[resultsCallBack]&url=[escapedUrlToMinify]

例如,呼叫http://b1t.co/Site/api/External/MakeUrlWithGet?callback=whateverJavascriptName&url=google.com

会回来

whateverJavascriptName({"success":true,"url":"http://google.com","shortUrl":"http://b1t.co/54"});

因此,当将该get作为src加载到您的js中时,它将自动运行您应实现为回调函数的任何JavascriptName:

function minifyResultsCallBack(data)
{
    document.getElementById("results").innerHTML = JSON.stringify(data);
}

要真正进行JSONP调用,您可以通过几种方式(包括使用jQuery)来实现,但这是一个纯JS示例:

function minify(urlToMinify)
{
   url = escape(urlToMinify);
   var s = document.createElement('script');
   s.id = 'dynScript';
   s.type='text/javascript';
   s.src = "http://b1t.co/Site/api/External/MakeUrlWithGet?callback=resultsCallBack&url=" + url;
   document.getElementsByTagName('head')[0].appendChild(s);
}

这篇文章提供了一个分步示例和一个jsonp Web服务进行练习:

一个使用JSONP的简单示例。

client.html

    <html>
    <head>
   </head>
     body>


    <input type="button" id="001" onclick=gO("getCompany") value="Company"  />
    <input type="button" id="002" onclick=gO("getPosition") value="Position"/>
    <h3>
    <div id="101">

    </div>
    </h3>

    <script type="text/javascript">

    var elem=document.getElementById("101");

    function gO(callback){

    script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = 'http://localhost/test/server.php?callback='+callback;
    elem.appendChild(script);
    elem.removeChild(script);


    }

    function getCompany(data){

    var message="The company you work for is "+data.company +"<img src='"+data.image+"'/   >";
    elem.innerHTML=message;
}

    function getPosition(data){
    var message="The position you are offered is "+data.position;
    elem.innerHTML=message;
    }
    </script>
    </body>
    </html>

server.php

  <?php

    $callback=$_GET["callback"];
    echo $callback;

    if($callback=='getCompany')
    $response="({\"company\":\"Google\",\"image\":\"xyz.jpg\"})";

    else
    $response="({\"position\":\"Development Intern\"})";
    echo $response;

    ?>    

在理解JSONP之前,您需要了解JSON格式和XML。当前,Web上最常用的数据格式是XML,但是XML非常复杂。这使用户不方便处理嵌入在网页中的内容。

为了使JavaScript可以轻松地交换数据,甚至作为数据处理程序,我们根据JavaScript对象使用措辞,并开发了一种简单的数据交换格式,即JSON。JSON可以用作数据或JavaScript程序。

JSON可以直接嵌入JavaScript中,使用它们可以直接执行某些JSON程序,但是由于安全性限制,浏览器沙箱机制会禁用跨域JSON代码执行。

为了使JSON在执行后可以传递,我们开发了JSONP。JSONP通过JavaScript回调功能和<script>标签绕过了浏览器的安全限制。

简而言之,它解释了什么是JSONP,解决了什么问题(何时使用)。

TL; DR

JSONP是一种古老的技巧,它是为了绕过安全限制而创建的,该安全限制禁止我们从其他服务器(不同来源*获取JSON数据

该技巧通过使用一个<script>从该位置请求JSON 标签来实现,例如:{ "user":"Smith" },但包装在一个函数中,即实际的JSONP(“带有填充的JSON”):

peopleDataJSONP({"user":"Smith"})

以这种形式接收它使我们能够使用peopleDataJSONP函数中的数据JSONP是一种不好的做法,请不要使用它(请参阅下文)

问题

假设我们正在浏览ourweb.com,我们想从中获取JSON数据(或实际上是任何原始数据)anotherweb.com如果我们要使用GET请求(如XMLHttpRequestfetch呼叫$.ajax等),我们的浏览器会告诉我们,这个丑陋的错误是不允许的:

Chrome CORS控制台错误

如何获取我们想要的数据?好吧,<script>标签不受整个服务器(来源*)的限制!这就是为什么我们可以从任何服务器(例如CDN)加载jQuery或Google Maps之类的库而不会出现任何错误。

要点:如果考虑一下,这些库是实际的,可运行的JS代码(通常是内置所有逻辑的庞大函数)。但是原始数据?JSON数据不是代码没什么可跑的。这只是纯数据。

因此,无法处理或操纵我们的宝贵数据。浏览器将下载我们<script>标记指向的数据,并且在处理时会抱怨:

wtf是{"user":"Smith"}我们加载的废话吗?这不是代码。我无法计算,语法错误!

JSONP骇客

The old/hacky way to utilize that data? We need that server to send it with some logic, so when it's loaded, your code in the browser will be able to use said data. So the foreign server sends us the JSON data inside a JS function. The data itself is set up as that function's input. It looks like this:

peopleDataJSONP({"user":"Smith"})

which makes it JS code our browser will parse without complaining! Exactly like it does with the jQuery library.
Now, to get it like that, the client "asks" the JSONP-friendly server for it, usually done like this:

<script src="https://anotherweb.com/api/data-from-people.json?myCallback=peopleDataJSONP"></script>

Our browser will receive the JSONP with that function name, hence we need a function with the same name in our code, like this:

const peopleDataJSONP = function(data){
  alert(data.user); // "Smith"
}

Or like this, same outcome:

function peopleDataJSONP(data){
  alert(data.user); // "Smith"
}

浏览器将下载并运行JSONP,它调用我们的function,其中参数data为我们的JSON。现在,我们可以随意处理数据。

不要使用JSONP,请使用CORS

JSONP是一个跨站点黑客,但有一些缺点:

  • 我们只能执行GET请求
  • 由于这是一个由简单脚本标签触发的GET请求,因此我们不会收到有用的错误或进度信息
  • 还存在一些安全问题,例如在客户端JS代码中运行,可能会更改为恶意有效负载。
  • 它仅解决JSON数据的问题,但是Same-Origin安全策略适用于其他数据(WebFonts,使用drawImage()绘制的图像/视频...)
  • 它不是很优雅也不可读。

要点是,现在不需要使用它了

JSONP是从另一台服务器获取JSON数据的技巧,但是如果我们需要其他类型的跨站点内容,则会违反相同的安全原则(Same-Origin)。

您应该在这里阅读有关CORS的信息,但要点是:

跨域资源共享(CORS)是一种机制,该机制使用附加的HTTP标头来告诉浏览器使在一个来源运行的Web应用程序可以访问来自另一个来源的选定资源。Web应用程序请求其来源(域,协议或端口)不同的资源时,将执行跨域HTTP请求。


* origin由3种东西定义:protocolporthost因此,例如,https://web.comhttp://web.com(不同协议)和https://web.com:8081(不同端口)以及https://thatotherweb.net明显不同的主机)的起源不同

已经给出了很好的答案,我只需要以javascript代码块的形式给出我的作品(我还将为跨域请求提供更现代,更好的解决方案:带有HTTP标头的CORS):

JSONP:

1. client_jsonp.js

$.ajax({
    url: "http://api_test_server.proudlygeek.c9.io/?callback=?",
    dataType: "jsonp",
    success: function(data) {
        console.log(data);    
    }
});​​​​​​​​​​​​​​​​​​

2. server_jsonp.js

var http = require("http"),
    url  = require("url");

var server = http.createServer(function(req, res) {

    var callback = url.parse(req.url, true).query.callback || "myCallback";
    console.log(url.parse(req.url, true).query.callback);

    var data = {
        'name': "Gianpiero",
        'last': "Fiorelli",
        'age': 37
    };

    data = callback + '(' + JSON.stringify(data) + ');';

    res.writeHead(200, {'Content-Type': 'application/json'});
    res.end(data);
});

server.listen(process.env.PORT, process.env.IP);

console.log('Server running at '  + process.env.PORT + ':' + process.env.IP);

CORS

3.client_cors.js

$.ajax({
    url: "http://api_test_server.proudlygeek.c9.io/",
    success: function(data) {
        console.log(data);    
    }
});​

4. server_cors.js

var http = require("http"),
    url  = require("url");

var server = http.createServer(function(req, res) {
    console.log(req.headers);

    var data = {
        'name': "Gianpiero",
        'last': "Fiorelli",
        'age': 37
    };

    res.writeHead(200, {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*'
    });

    res.end(JSON.stringify(data));
});

server.listen(process.env.PORT, process.env.IP);

console.log('Server running at '  + process.env.PORT + ':' + process.env.IP);

JSONP表示带有Padding的JSON

这是该站点,上面有很多示例并给出了从最简单的使用此技术到最先进的平面JavaScript的解释:

w3schools.com / JSONP

上面描述的我最喜欢的技术之一是Dynamic JSON Result,它允许将JSON发送到URL参数中PHP文件,并允许PHP文件还根据获得的信息返回JSON对象

jQuery之类的工具也具有使用JSONP的功能

jQuery.ajax({
  url: "https://data.acgov.org/resource/k9se-aps6.json?city=Berkeley",
  jsonp: "callbackName",
  dataType: "jsonp"
}).done(
  response => console.log(response)
);
本文地址:http://javascript.askforanswer.com/shenmeshijsonpweishenmechuangjianta.html
文章标签: ,   ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!