23

我需要从网站向托管在另一个域中的 REST Web 服务发出 AJAX 请求。

尽管这在 Internet Explorer 中运行良好,但其他浏览器(例如 Mozilla 和 Google Chrome)施加了更严格的安全限制,禁止跨站点 AJAX 请求。

问题是我无法控制域或托管站点的 Web 服务器。这意味着我的 REST Web 服务必须在其他地方运行,并且我无法实施任何重定向机制。

下面是进行异步调用的 JavaScript 代码:

var serviceUrl = "http://myservicedomain";
var payload = "<myRequest><content>Some content</content></myRequest>";
var request = new XMLHttpRequest();
request.open("POST", serviceUrl, true); // <-- This fails in Mozilla Firefox amongst other browsers
request.setRequestHeader("Content-type", "text/xml");
request.send(payload);

我怎样才能在 Internet Explorer 以外的其他浏览器中进行这项工作?

4

8 回答 8

14

也许JSONP可以提供帮助。

注意,您必须将消息更改为使用 json 而不是 xml

编辑

flickr 和twitter等主要网站支持带有回调等的 jsonp

于 2008-12-02T10:17:04.113 回答
5

标记为答案的帖子是错误的:iframe 文档无法访问父级。同源策略双向工作。

事实是,不可能以任何方式使用 xmlhttprequest 来使用基于 rest 的 web 服务。从不同域(没有任何框架)加载数据的唯一方法是使用 JSONP。任何其他解决方案都需要位于您自己域上的服务器端代理,或位于远程域上的客户端代理和某种跨站点通信(如easyXDM)来在文档之间进行通信。

于 2009-07-05T21:37:08.793 回答
3

这在 IE 中有效的事实是 IE 的安全问题,而不是功能。

不幸的是,跨站点脚本被禁止,并且公认的解决方法是通过您自己的域代理请求:您真的没有能力添加或修改服务器端代码吗?

此外,次要解决方法 - 涉及通过脚本标签获取数据 - 仅支持 GET 请求,您可以使用 SOAP 服务破解它,但对于您描述的 RESTful 服务的 POST 请求则不支持。

我真的不确定是否存在 AJAX 解决方案,您可能会回到 <form> 解决方案。

于 2008-12-02T10:22:36.583 回答
3

不是很明确的解决方法(但有效)是使用 iframe 作为对其他站点的请求的容器。问题是,父级无法访问 iframe 的内容,只能导航 iframe 的“src”属性。但是 iframe 内容可以访问父级的内容。

因此,如果 iframe 的内容知道,他们可以调用父页面中的一些 javascript 内容或直接访问父页面的 DOM。

编辑: 示例:

function ajaxWorkaroung() {
    var frm = gewtElementById("myIFrame")
    frm.src = "http://some_other_domain"
}
function ajaxCallback(parameter){
    // this function will be called from myIFrame's content
}
于 2008-12-02T12:11:51.713 回答
2

让您的服务域接受跨域资源共享 (CORS)。

典型场景:大多数符合 CORS 的浏览器会首先发送一个 OPTIONS 标头,服务器应向该标头返回有关接受哪些标头的信息。如果标头满足服务对所提供请求的要求(允许的方法为 GET 和 POST、Allowed-Origin * 等),则浏览器将使用适当的方法(GET、POST 等)重新发送请求。

这一点与您使用 IE 时的所有内容相同,或者更简单地说,如果您发布到同一个域。

注意事项:一些服务开发SDK(特别是WCF)会尝试处理请求,在这种情况下你需要预处理OPTIONS方法来响应请求,避免在服务器上调用该方法两次。

简而言之,问题出在服务器端。

编辑IE 9 及更低版本的 CORS 存在一个问题,即它没有完全实现。幸运的是,您可以通过从服务器端代码调用服务并让它通过您的服务器返回来解决这个问题(例如 mypage.aspx?service=blah&method=blahblah&p0=firstParam=something)。从这里开始,您的服务器端代码应该实现请求/响应流模型。

于 2012-07-07T14:02:45.643 回答
1

只需在您的原始域上使用服务器端代理。这是一个例子:http: //jquery-howto.blogspot.com/2009/04/cross-domain-ajax-querying-with-jquery.html

于 2012-01-04T06:43:33.160 回答
0

这也可以使用本地网络服务器设置来完成,该本地设置使用正确的参数调用 curl 并返回 curl 输出。

应用程序.rb

require 'sinatra'
require 'curb'

set :views,lambda {"views/"+self.name.to_s.downcase.sub("controller","")}
set :haml, :layout => :'../layout', :format => :html5, :escape_html=>true
disable :raise_errors

get '/data/:brand' do
  data_link =  "https://externalsite.com/#{params[:brand]}"
  c = Curl::Easy.perform(data_link)
  c.body_str
end

向 localhost:4567/data/something 发送 ajax 请求将从 externalsite.com/something 返回结果。

于 2012-08-26T09:28:40.137 回答
0

另一种选择是在您自己的域上设置 CNAME 记录以“屏蔽”远程域主机名。

于 2013-12-07T05:05:58.767 回答