对 JSONP 请求的工作方式感到困惑
Posted
技术标签:
【中文标题】对 JSONP 请求的工作方式感到困惑【英文标题】:Confused on how a JSONP request works 【发布时间】:2012-04-28 21:39:01 【问题描述】:我无法理解 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 请求中检索/使用数据吗?
【问题讨论】:
Please explain JSONP 的可能重复项 【参考方案1】:回调是您在自己的代码中定义的函数。 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 不能从浏览器中做到这一点),但绝对值得注意的是这可能很危险。【参考方案2】:
编辑:正如乔恩所说,有更好的解释here。
JSONP 使用脚本标签来进行跨源请求。由于脚本标签用于包含脚本,因此服务器需要返回有效的 JavaScript。我们将 JavaScript 提供给客户端的方式是通过函数调用。您告诉服务器您希望脚本调用什么函数,然后在本地创建该函数。脚本加载完成后,将调用您的函数,并将数据作为参数。
因此,如果您在您提到的 URL 上执行了 JSONP 请求,并且它返回了您提到的有效负载,那么您将通过执行以下操作来获取您的数据:
function parseResponse(data)
console.log("JSONP request complete", data);
【讨论】:
返回的数据如何神奇地成为parseRepsonse函数的参数? @JohnBaum 因为服务器创建了将被调用的 JS 代码?【参考方案3】:函数名 parseResponse 以某种方式传递给服务器 返回的数据成为该函数的参数
好像你自己解释过,jsonp=parseResponse
是这个应用程序设置回调函数的方式,所以它返回一个函数,里面有你的json数据,看起来像
parseResponse("Name": "Foo", "Id" : 1234, "Rank": 7);
它在加载时被调用,并由您的 JS 中的函数处理,例如:
function parseResponse(data)
console.log(data);
【讨论】:
以上是关于对 JSONP 请求的工作方式感到困惑的主要内容,如果未能解决你的问题,请参考以下文章