对 JSONP 请求的工作方式感到困惑

IT技术 javascript ajax jsonp
2021-03-01 20:17:55

我无法理解 jsonp 请求如何工作的细节。我已经阅读了包括 jsonp 上的 wiki 在内的几个来源,但仍然对回调如何在进行 jsonp 调用时实际获取从服务器返回的函数感到困惑。例如在wiki中,请求的来源设置为:

src="http://server2.example.com/RetrieveUser?UserId=1234&jsonp=parseResponse"

jsonp = parseResponse 究竟是做什么/意味着什么?然后他们继续说有效载荷是:

parseResponse({"Name": "Foo", "Id" : 1234, "Rank": 7});

这是如何运作的?我对整个回调功能感到困惑。函数名称 parseResponse 被传递给服务器,并且返回的数据以某种方式成为该函数的参数?有人可以清楚地解释一下如何从 jsonp 请求中检索/使用数据吗?

3个回答

回调是您在自己的代码中定义的函数。jsonp 服务器将使用与您指定的回调函数名称相同的函数调用来包装其响应。

这是怎么回事:

1) 您的代码创建了 JSONP 请求,这会产生一个如下所示的新<script>块:

<script src="http://server2.example.com/RetrieveUser?UserId=1234&jsonp=parseResponse"></script>

2) 该新脚本标签由您的浏览器执行,从而向 JSONP 服务器发出请求。它回应

parseResponse({"Name": "Foo", "Id" : 1234, "Rank": 7});

3) 由于此请求来自脚本标记,因此与您从字面上放置的请求几乎完全相同

<script>
    parseResponse({"Name": "Foo", "Id" : 1234, "Rank": 7});
</script>

进入你的页面。

4) 现在这个新脚本已经从远程服务器加载,现在将被执行,它唯一要做的就是一个函数调用,parseResponse()将 JSON 数据作为函数调用的唯一参数传入。

所以在你的代码中的其他地方,你会有:

function parseResponse(data) {
     alert(data.Name); // outputs 'Foo'
}

基本上,JSONP 是一种绕过浏览器同源脚本安全策略的方法,通过让第 3 方服务器将函数调用直接注入您的页面。请注意,这是设计上非常不安全的。您依赖于远程服务是可敬的并且没有恶意。没有什么可以阻止糟糕的服务返回一些窃取您的银行/facebook/任何凭据的 JS 代码。例如...... JSONP 响应可能是

 internalUseOnlyFunction('deleteHarddrive');

而不是 parseReponse(...)。如果远程站点知道您的代码的结构,它就可以使用该代码执行任意操作,因为您已经敞开了大门,允许该站点做任何想做的事情。

我不会举一个例子deleteHardDrive(javascript 不能从浏览器中做到这一点),但绝对值得注意的是,这可能很危险。
2021-05-10 20:17:55

编辑:正如乔恩说,那里是它的一个办法更好的解释这里

JSONP 使用脚本标签来发出跨源请求。由于脚本标签用于包含脚本,因此服务器需要返回有效的 JavaScript。我们将 JavaScript 提供给客户端的方式是通过函数调用。您告诉服务器您希望脚本调用什么函数,然后在本地创建该函数。脚本加载完成后,将使用数据作为参数调用您的函数。

因此,如果您在您提到的 URL 上执行了 JSONP 请求,并且它返回了您提到的有效负载,您将通过执行以下操作来获取您的数据:

function parseResponse(data) {
    console.log("JSONP request complete", data);
}
@JohnBaum 因为服务器创建了将被调用的 JS 代码?
2021-05-13 20:17:55
返回的数据是如何神奇地成为parseRepsonse函数的参数的?
2021-05-14 20:17:55

函数名称 parseResponse 被传递给服务器,并且以某种方式返回的数据成为该函数的参数

看起来你刚刚自己解释过,jsonp=parseResponse这个应用程序是如何设置回调函数的,所以它返回一个包含你的json数据的函数,看起来像

parseResponse({"Name": "Foo", "Id" : 1234, "Rank": 7});

它在加载时被调用,并由您的 JS 中的函数处理,例如:

function parseResponse(data){
    console.log(data);
}