简体   繁体   English

跨站点AJAX请求

[英]Cross-site AJAX requests

I need to make an AJAX request from a website to a REST web service hosted in another domain. 我需要从网站向另一个域中托管的REST Web服务发出AJAX请求。

Although this is works just fine in Internet Explorer, other browsers such as Mozilla and Google Chrome impose far stricter security restrictions, which prohibit cross-site AJAX requests. 虽然这在Internet Explorer中运行良好,但其他浏览器(如Mozilla和Google Chrome)实施了更为严格的安全限制,禁止跨站点AJAX请求。

The problem is that I have no control over the domain nor the web server where the site is hosted. 问题是我无法控制域或托管站点的Web服务器。 This means that my REST web service must run somewhere else, and I can't put in place any redirection mechanism. 这意味着我的REST Web服务必须在其他地方运行,我无法实现任何重定向机制。

Here is the JavaScript code that makes the asynchronous call: 以下是进行异步调用的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);

How can I have this work in other browsers beside Internet Explorer? 如何在Internet Explorer旁边的其他浏览器中使用此功能?

maybe JSONP can help. 也许JSONP可以提供帮助。

NB youll have to change your messages to use json instead of xml NB你必须改变你的消息使用json而不是xml

Edit 编辑

Major sites such as flickr and twitter support jsonp with callbacks etc flickr和twitter等主要网站都支持jsonp回调等

The post marked as the answer is erroneous: the iframes document is NOT able to access the parent. 标记为答案的帖子是错误的:iframes文档无法访问父级。 The same origin policy works both ways. 相同的原产地政策有两种方​​式。

The fact is that it is not possible in any way to consume a rest based webservice using xmlhttprequest. 事实是,不可能以任何方式使用xmlhttprequest来使用基于休息的web服务。 The only way to load data from a different domain (without any framework) is to use JSONP. 从不同域(没有任何框架)加载数据的唯一方法是使用JSONP。 Any other solutions demand a serverside proxy located on your own domain, or a client side proxy located on the remote domain and som sort of cross-site communication (like easyXDM ) to communicate between the documents. 任何其他解决方案都需要位于您自己的域上的服务器端代理,或位于远程域上的客户端代理以及某些跨站点通信(如easyXDM )来在文档之间进行通信。

The fact that this works in IE is a security issue with IE, not a feature. 在IE中工作的事实是IE的安全问题,而不是功能。

Unfortunately cross-site scripting is prohibited, and the accepted work around is to proxy the requests through your own domain: do you really have no ability to add or modify server side code? 不幸的是,禁止跨站点脚本,并且接受的解决方法是通过您自己的域代理请求:您真的无法添加或修改服务器端代码吗?

Furthermore, the secondary workaround - involving the aquisition of data through script tags - is only going to support GET requests, which you might be able to hack with a SOAP service, but not so much with the POST request to a RESTful service you describe. 此外,辅助解决方法 - 涉及通过脚本标记获取数据 - 仅支持GET请求,您可能能够使用SOAP服务进行攻击,但对于您描述的RESTful服务的POST请求则没有那么多。

I'm really not sure an AJAX solution exists, you might be back to a <form> solution. 我真的不确定AJAX解决方案是否存在,您可能会回到<form>解决方案。

The not very clear workaround (but works) is using iframe as container for requests to another sites. 不太清楚的解决方法(但有效)是使用iframe作为对其他站点的请求的容器。 The problem is, the parent can not access iframe's content, can only navigate iframe's "src" attribut. 问题是,父母无法访问iframe的内容,只能导航iframe的“src”属性。 But the iframe content can access parent's content. 但iframe内容可以访问父母的内容。

So, if the iframe's content know, they can call some javascript content in parent page or directly access parent's DOM. 因此,如果iframe的内容知道,他们可以在父页面中调用一些javascript内容或直接访问父级的DOM。

EDIT: Sample: 编辑:示例:

function ajaxWorkaroung() {
    var frm = gewtElementById("myIFrame")
    frm.src = "http://some_other_domain"
}
function ajaxCallback(parameter){
    // this function will be called from myIFrame's content
}

Make your service domain accept cross origin resource sharing (CORS). 使您的服务域接受跨源资源共享(CORS)。

Typical scenario: Most CORS compliant browsers will first send an OPTIONS header, to which, the server should return information about which headers are accepted. 典型情况:大多数符合CORS的浏览器将首先发送一个OPTIONS标头,服务器应该返回有关接受哪些标头的信息。 If the headers satisfy the service's requirements for the request provided (Allowed Methods being GET and POST, Allowed-Origin *, etc), the browser will then resend the request with the appropriate method (GET, POST, etc.). 如果标头满足服务对所提供的请求的要求(允许的方法为GET和POST,Allowed-Origin *等),则浏览器将使用适当的方法(GET,POST等)重新发送请求。

Everything this point forward is the same as when you are using IE, or more simply, if you were posting to the same domain. 此处的所有内容与您使用IE时相同,或者更简单地说,如果您发布到同一个域。

Caviots: Some service development SDK's (WCF in particular) will attempt to process the request, in which case you need to preprocess the OPTIONS Method to respond to the request and avoid the method being called twice on the server. Caviots:一些服务开发SDK(特别是WCF)将尝试处理请求,在这种情况下,您需要预处理OPTIONS方法以响应请求并避免在服务器上调用两次方法。

In short, the problem lies server-side. 简而言之,问题在于服务器端。

Edit There is one issue with IE 9 and below with CORS, in that it is not fully implemented. 编辑 IE 9及以下版本与CORS有一个问题,因为它没有完全实现。 Luckily, you can solve this problem by making your calls from server-side code to the service and have it come back through your server (eg mypage.aspx?service=blah&method=blahblah&p0=firstParam=something). 幸运的是,您可以通过从服务器端代码调用服务并通过服务器返回来解决此问题(例如mypage.aspx?service = blah&method = blahblah&p0 = firstParam = something)。 From here, your server side code should implement a request/response stream model. 从这里开始,您的服务器端代码应该实现请求/响应流模型。

Just use a server side proxy on your origin domain. 只需在源域上使用服务器端代理即可。 Here is an example: http://jquery-howto.blogspot.com/2009/04/cross-domain-ajax-querying-with-jquery.html 这是一个例子: http//jquery-howto.blogspot.com/2009/04/cross-domain-ajax-querying-with-jquery.html

This can also be done using a webserver setup localy that calls curl with the correct arguments and returns the curl output. 这也可以使用webserver设置localy来完成,该设置使用正确的参数调用curl并返回curl输出。

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

Sending an ajax request to localhost:4567/data/something will return the result from externalsite.com/something. 向localhost发送ajax请求:4567 / data / something将返回externalsite.com/something的结果。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM