2008-12-02 71 views
22

我需要从一个网站向另一个域中托管的REST Web服务发出AJAX请求。跨站点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旁边其他浏览器这项工作?

+1

@PhiLho在这种情况下,我的目标是调用托管在不同域上的REST服务,不包括动态内容。 – 2008-12-02 19:56:26

回答

14

也许JSONP可以提供帮助。

NB youll必须改变你的消息,而不是使用XML JSON

编辑

主要网站如Flickr和与回调等

+0

这可能工作,但JSONP是承认有什么错:) – annakata 2008-12-02 10:24:30

+0

这种方法有多受欢迎?这似乎是一种实验。 – 2008-12-02 10:37:11

+0

@annakata很明显,但他有点不知所措,他没有处理Web服务器等,所以使用代理服务器不在窗口。我不是在这里评论他的情况,只是为他的问题提供一个可能的解决方案。 – redsquare 2008-12-02 10:50:39

3

,这在IE的事实twitter支持JSONP IE的安全问题,而不是功能。

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

此外,第二个解决方法 - 涉及通过脚本标记获取数据 - 仅支持GET请求,您可能会使用SOAP服务攻击GET请求,但与POST请求不同的是RESTful你描述的服务。

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

3

不是很清楚的解决方法(但有效)是使用iframe作为对其他网站的请求的容器。问题是,父母无法访问iframe的内容,只能导航iframe的“src”attribut。但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 
} 
5

标记为答案的帖子是错误的:I帧文件无法访问父。相同的原产地政策适用于两种方式。

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

2

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

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

这一点的所有内容都与您使用IE时相同,或者更简单地说,如果您发布到同一个域中。鱼子酱:某些服务开发SDK(特别是WCF)将尝试处理请求,在这种情况下,您需要预处理OPTIONS方法以响应请求并避免在服务器上调用两次该方法。

总之,问题在于服务器端。

编辑 IE9和CORS有一个问题,因为它没有完全实现。幸运的是,您可以通过从服务器端代码访问服务并通过服务器返回(例如mypage.aspx?service = blahblah & p0 = firstParam = something)来解决此问题。从这里开始,你的服务器端代码应该实现一个请求/响应流模型。

0

这也可以使用webserver安装程序localy完成,该程序使用正确的参数调用curl并返回curl输出。

app.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 

Ajax请求到localhost:4567 /数据/将东西从externalsite.com/something返回结果。

0

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