2008-12-02 188 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記錄以「屏蔽」遠程域主機名。