jQuery .ajax 和同源策略

Posted

技术标签:

【中文标题】jQuery .ajax 和同源策略【英文标题】:jQuery .ajax and Same Origin Policy 【发布时间】:2012-08-22 08:33:04 【问题描述】:

我有一个正在运行的 html5/JS 应用程序,我正在尝试将其移植到浏览器进行演示。该应用是为在车辆中运行而构建的,并使用车辆制造商的网络 API 来获取/发布请求。

对于这个的浏览器版本,我正在尝试使用 jQuery 来获取/发布。但是,我立即遇到了问题。

XMLHttpRequest cannot load http://<API I AM CALLING>. Origin null is not allowed by Access-Control-Allow-Origin.

我已经研究过同源政策,但仍然没有完全理解它。我可以浏览到正在使用的 URL,并查看我正在尝试检索的 JSON。

环顾网络,很多人建议在我的 ajax 调用中将 JSONP 指定为 dataType。我试了一下,没有成功。

            $.ajax(
                url: url,
                type: "GET",
                dataType: "jsonp",
                success: function (data, textStatus, jqXHR) 
                    log("success getting JSON from " + url);
                    success(data);
                ,
                error: function (jqXHR, textStatus, errorThrown) 
                    log("error getting JSON from " + url + ", code " + JSON.stringify(jqXHR));
                    log("textStatus is " + textStatus);
                    log("errorThrown is " + errorThrown);
                ,
            );

我的控制台中出现错误:

Uncaught SyntaxError: Unexpected token : 

之后,使用我的错误回调。

error getting JSON from http://<API I AM CALLING>, code "readyState":4,"status":200,"statusText":"success"
textStatus is parsererror
errorThrown is Error: jQuery180006523256213404238_1346098086632 was not called 

看起来服务器正在响应我需要的 JSON 数据。但是,我猜测 jQuery 期望这些数据被包装在一个函数中,所以它无法解析它。

我无法控制我正在调用其 API 的服务器。由于数据正在返回浏览器,我觉得必须有某种方式来访问它。

注意: App只针对webkit浏览器,其他的我不需要支持。将 dataType 保留为“json”只会导致 Chrome 出现问题,但由于不同的安全策略,Safari 似乎可以正常工作。寻找代码解决方法,而不是简单地使用特殊参数启动 Chrome。即使我在 Apache 上托管我的代码,Chrome 中仍然会发生这种情况,因此它不仅限于我尝试在本地打开 index.html。

【问题讨论】:

您不能简单地从 json 更改为 jsonp 而不更新 API 以返回有效的 jsonpJSON != JSONP 我意识到这一点,但它确实绕过了同源策略,并且服务器能够使用我需要的 JSON 进行响应。我只需要弄清楚如何获得这些数据。 如果JSONP 无效,您将无法使用它。另一个选择是使用 JSON 数据类型并让您的服务器返回 CORS 标头。 就像我说的,无法控制服务器 啊,我错过了那部分。然后您必须使用某种代理,例如 YQL 或您自己的服务器上的代理来为您获取数据,使其成为有效的同域 json 请求或有效的跨域 jsonp 请求。跨度> 【参考方案1】:

一种可能的解决方案是编写一个服务来代理您想要的 JSON 服务并返回 JSONP。我已经编写了许多这样的代理服务,因此我可以绕过相同的来源策略。

例如:http://high-cloud-3702.heroku.com/

此服务是城市词典的 jsonp 代理。

您可以非常轻松地在 Sinatra 中编写这样的代理,并将其免费托管在 Heroku 上。

这样的代理的关键是这段代码:

get '/' do
  callback = params.delete('callback') # jsonp
  json = <function_to_get_data_here>.to_json

  if callback
    content_type :js
    response = "#callback(#json)" 
  else
    content_type :json
    response = json
  end
  response
end

【讨论】:

OP 可以从他的服务器返回 JSON。 当他说“我无法控制我正在调用其 API 的服务器”时,我想我认为 OP 无法控制他正在调用的服务器。但是,如果他可以在服务所在的同一域上托管他的应用程序,他就可以进行常规 JSON 调用...

以上是关于jQuery .ajax 和同源策略的主要内容,如果未能解决你的问题,请参考以下文章

JS实现的ajax和同源策略

ajax-josnp(基于js,jQuery)

Ajax 跨域和同源策略的解释和使用,使用jQuery跨域,模板引擎artTemplate的使用详细解释+案例

JS实现的ajax和同源策略

JS实现的ajax和同源策略

JS实现的ajax和同源策略