10
  1. 我看不出 JSONP 中的回调函数与 AJAX 中的成功回调函数有何不同。

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

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

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

困惑,马克斯

4

3 回答 3

20

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

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

因此,这两种通信方法的工作方式完全不同。只有 ajax 调用可以是同步的。根据<script>标签插入的性质,JSONP 调用始终是异步的。

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

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

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

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

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

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

但是,按照我们今天的方式,只要 Yahoo 不支持使用相同 Web cookie 的 JSONP 接口,它就不会受到未经授权的 JSONP 请求的影响。

以下是关于跨域 ajax 的危险以及为什么必须防止它的其他一些很好的文章:

为什么跨域 Ajax 是一个安全问题?

为什么不允许跨域 AJAX 调用?

为什么跨域 AJAX 请求被标记为“安全风险”?

于 2012-04-23T23:50:17.677 回答
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(如果您的页面上运行了不受信任的脚本,那么您无论如何都会被淹没)。

于 2012-04-24T00:05:00.713 回答
1

根本区别在于,出于某种原因,加载位于其他域(通过 script 标签)的 javascript 文件是完全可以的,但默认情况下加载其他跨域资源是不行的。

我同意你,因为这种划分似乎相当武断。在jQuery中,当您执行 JSONP 调用时,实际上是在创建脚本标记、加载资源,然后 jQuery 库通过调用该 JSONP 结果中定义的函数来执行您的脚本。

在我看来,我想不出允许跨域 AJAX 引入的额外攻击向量,通过允许跨域脚本加载,它还没有扩大,这是到处使用的常见做法(googleCDN 的 jQuery,广告脚本,谷歌分析,和无数其他人)。

来自维基百科

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.

于 2012-04-23T23:53:20.133 回答