我不知道JSONP与AJAX有什么不同

时间:2012-04-23 23:37:14

标签: javascript jsonp

  1. 我没有看到JSONP中的回调函数与AJAX中的成功回调函数有什么不同。

  2. 鉴于#1,我看不出它是如何从根本上更加安全。

  3. 与AJAX的人工同域约束的唯一区别是什么?

  4. 为什么AJAX不能只允许跨域请求;如果这可能导致安全漏洞,攻击不会只是XSS一个JSONP请求吗?

  5. 困惑, 最大

3 个答案:

答案 0 :(得分:20)

ajax调用是从客户端直接到服务器的实际HTTP请求。 Ajax调用可以是同步的(阻塞直到完成)或异步。由于同源安全保护,除非目标服务器明确允许使用CORS的跨源请求,否则只能对网页所在的服务器进行ajax调用。

JSONP调用是一个有趣的hack,<script>标记允许跨源通信。在JSONP调用中,客户端创建一个脚本标记,并在其上放置一个带有callback=xxxx查询参数的URL。该脚本请求(通过脚本标签插入)由浏览器发送到外部服务器。浏览器只是认为它要求一些javascript代码。然后,服务器为此调用创建一些特殊的javascript,并且当浏览器返回时将由浏览器执行该javascript,服务器将函数调用放入callback=xxxx查询中指定的函数参数。通过将数据传递给该函数来定义变量,服务器可以将数据传递回客户端。对于JSONP,客户端和服务器必须就JSONP调用的工作方式以及数据的定义方式进行合作。客户端无法对不明确支持JSONP的服务器进行JSONP调用,因为服务器必须构建完全正确的JSONP响应类型,否则它将无法正常工作。

因此,这两种沟通方法完全不同。只有ajax调用可以是同步的。根据{{​​1}}标记插入的性质,JSONP调用始终是异步的。

在Ajax调用中,响应在ajax事件处理程序中返回。

在JSONP调用中,当返回的Javascript调用您的函数时,响应就会出现。

在某些方面,JSONP是一个绕过跨源安全机制的安全漏洞。但是,您只能调用明确选择支持类似JSONP机制的服务器,因此如果服务器不希望您能够跨域调用它,它可以通过不支持JSONP来阻止它。您无法定期对这些其他服务器进行ajax调用。

浏览器制造商无法真正消除这个漏洞,因为如果他们做了数以万计的网页会破坏已经使用JSONP或从其他域加载脚本。例如,网络上使用jQuery关闭Google或Microsoft CDN的每个页面都会中断,因为浏览器不允许从跨域域下载javascript。

JSONP主要是作为解决方案发明的,可以进行跨源请求。但是,由于JSONP需要显式服务器支持才能工作,因此它不是真正的安全问题,因为只能对明确决定允许该类型的跨源调用的服务器进行JSONP调用。 JSONP的使用现在比过去少得多,因为CORS被发明为一种更优雅的控制/允许方式。 CORS代表Cross Origin Resource Sharing,它为目标服务器提供了一种方法,可以准确地告诉Web浏览器允许哪种类型的跨源请求,甚至告诉它允许哪些网页域发出此类请求。它具有比JSONP更精细的控制,所有现代浏览器现在都支持CORS。

以下是跨源调用如何导致问题的示例。如果你可以从任何其他网页加载任意网页或进行任意的ajax调用,那么想象一下你已经在雅虎的其他浏览器窗口中登录了你的webmail界面。这意味着您的cookie设置为允许来自浏览器的请求从Yahoo获取数据。如果某个其他网页中的javascript被允许向雅虎发送网络邮件请求(这将自动附加您的cookie),那么它可以获取您的所有网络邮件数据并将其发送回其自己的网站。一个网站可以从任何其他网站上删除所有登录的数据。所有网络安全都将被打破。

但是,就我们今天的方式而言,只要雅虎不支持使用这些相同网络cookie的JSONP接口,就可以避免未经授权的JSONP请求。

以下是关于跨源ajax危险的一些其他好的文章以及必须要防止的原因:

Why the cross-domain Ajax is a security concern?

Why Cross-Domain AJAX call is not allowed?

Why are cross-domain AJAX requests labelled as a "security risk"?

答案 1 :(得分:2)

JSONP的回调是不是实际的回调。相反,JSONP通过脚本注入工作。例如,如果要进行JSONP调用,则将此脚本元素插入DOM:

<script src="http://example.com/ajaxendpoint?jsonp=parseResponse"></script>

服务器的响应将是这样的:

parseResponse({"json":"value"});

将在窗口的全局范围内评估。所以基本上JSONP就像一个远程exec(),在那里建议服务器创建要执行的字符串。

与Ajax 非常不同:使用JSONP,响应在脚本的全局范围内进行评估;使用XMLHttpRequest,响应以字符串形式接收,不进行评估。 (另外,JSONP只能与GET一起使用,而AJAX允许任何http方法。)

因此,对于你的第二个问题,“我不明白它是如何从根本上更安全的。”嗯,你是对的,JSONP实际上是 非常不安全 。服务器可以返回它想要的任何脚本,并将它想要的任何内容发送到您的浏览器!

跨域请求不安全,因为它们可用于向另一个域中的页面显示有关当前页面的信息。

你是对的,任何XSS攻击都可以使用JSONP。 CORS的目的不是为了阻止XSS(如果您在页面上运行了不受信任的脚本,则无论如何都会被冲洗掉。)

答案 2 :(得分:1)

根本区别在于,出于某种原因,加载位于其他域上的javascript文件(通过脚本标记)是完全正常的,但默认情况下加载其他跨域资源并不正常。

我和你在一起,因为描述似乎相当随意。在jQuery中,当您执行JSONP调用时,实际上您正在创建脚本标记,加载资源,然后jQuery库通过调用该JSONP结果中定义的函数来执行您的脚本。

在我看来,我无法想到通过允许跨域脚本加载而允许跨域AJAX引入的额外攻击向量,这是一种常用的做法(jQuery by googleCDN,广告脚本,谷歌分析,无数其他人。)

来自wikipedia

In addition, many legacy cross-domain operations predating JavaScript are not subjected to same-origin checks; one such example is the ability to include scripts across domains, or submit POST forms.