我瞭解AJAX跨域策略。 因此,我不能只通過ajax HTTP請求調用「http://www.google.com」,並在我的網站某處顯示 結果。AJAX跨域調用
我的dataType「JSONP」試了一下,實際上會工作,但我得到一個語法錯誤(顯然是因爲接收到的數據是不是JSON格式化)
是否有任何其他方法可行,從接收/顯示數據一個外地? iFrames遵循相同的政策?
我瞭解AJAX跨域策略。 因此,我不能只通過ajax HTTP請求調用「http://www.google.com」,並在我的網站某處顯示 結果。AJAX跨域調用
我的dataType「JSONP」試了一下,實際上會工作,但我得到一個語法錯誤(顯然是因爲接收到的數據是不是JSON格式化)
是否有任何其他方法可行,從接收/顯示數據一個外地? iFrames遵循相同的政策?
使用AJAX獲取跨域數據的唯一(簡單)方式是使用服務器端語言作爲代理,如Andy E所述。下面是一個小樣本如何實現使用jQuery是:
jQuery的部分:
$.ajax({
url: 'proxy.php',
type: 'POST',
data: {
address: 'http://www.google.com'
},
success: function(response) {
// response now contains full HTML of google.com
}
});
而PHP(proxy.php):
echo file_get_contents($_POST['address']);
這麼簡單。只要知道你可以或不可以用刮取的數據做什麼。
您需要動態地將腳本標記插入到引用數據的頁面中。使用JSONP,您可以在加載腳本時執行一些回調函數。
JSONP上的維基百科頁面有一個簡潔的例子;該腳本標籤:
<script type="text/javascript" src="http://domain1.com/getjson?jsonp=parseResponse">
</script>
將包裹在一個呼叫JSON數據返回parseResponse
:
parseResponse({"Name": "Cheeso", "Rank": 7})
(取決於getjson
腳本的配置上domain1.com)
的代碼要動態插入標籤會是這樣的:
var s = document.createElement("script");
s.src = "http://domain1.com/getjson?jsonp=parseResponse";
s.type = "text/javascript";
document.appendChild(s);
只有當您收到JSON數據或純文本或HTML格式時,這纔會起作用嗎? – jAndy 2010-04-01 08:19:38
@jAndy:這隻適用於JSONP(包括回調函數)數據。 – 2010-04-01 08:21:37
只適用於GET請求。沒有PUT,DELETE或POST。所以沒有RESTful接口。 – ProblemsOfSumit 2015-08-11 13:09:49
在我看來,JSONP是最好的選擇。試着弄清楚爲什麼你會得到語法錯誤 - 你確定收到的數據不是JSON嗎?那麼也許你以某種方式錯誤地使用了API。
您可以使用的另一種方式,但我不認爲它適用於您的情況,是在頁面中有一個iFrame,src位於您要調用的域中。讓它爲您打電話,然後使用JS在iFrame和頁面之間進行通信。這將繞過跨域,但前提是您可以在要調用的域中擁有iFrame的src。
@Nir:他得到了語法錯誤,因爲他在提取HTML而不是JSON。這將永遠不會與JSONP一起工作:-) – 2010-04-01 08:17:04
不幸的是(或幸運的是)沒有。跨域策略是有原因的,如果它很容易繞過它,那麼它作爲安全措施就不是很有效。除了JSONP,唯一的選擇是proxy the pages using your own server。
使用iframe時,它們受制於相同的策略。當然,您可以顯示來自外部域的數據,但您無法操作它。
你是什麼意思,「你不能操縱它」? 你不能將一些數據加載到iFrame中,並通過jQuery選擇器讀取數據? – jAndy 2010-04-01 08:50:36
@jAndy:不,在訪問跨不同域的文檔時,訪問被阻止到DOM的99%。跨文檔消息傳遞是可能的(使用HTML5 /現代瀏覽器),但必須由雙方實施。 – 2010-04-01 08:56:29
做一些研究之後,唯一的「解決方案」這個問題是調用:
if($.browser.mozilla)
netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');
這會問一個用戶,如果他讓網站繼續。在他確認後,所有 ajax調用,不管它的數據類型是否會被執行。
這適用於Mozilla瀏覽器,在IE < 8中,用戶必須以類似方式允許跨域調用 ,某些版本需要在瀏覽器選項中進行配置。
chrome/safari:到目前爲止,我沒有找到這些瀏覽器的配置標誌。
使用JSONP作爲數據類型會很好,但在我的情況下,我不知道我是否需要 來訪問該格式的數據。
另一種方法是使用HTML5 postMessage,它可以跨域使用,但我不能使用我的用戶訪問HTML5瀏覽器。
您並未將您的用戶推向HTML5瀏覽器,您正在爲他們提供服務:-) – 2010-08-27 14:39:24
我在2天內遇到了同樣的問題,並且找到了解決方案,並且Google搜索後很優雅。 我需要一些小部件客戶端的xss Ajax,這些小部件客戶端將數據流從層網站拉到我的Rails應用程序。 here's how I did.
我使用這段代碼進行跨域ajax調用,我希望它能幫助多個這裏。我使用Prototype庫,你可以做與jQuery或道場或別的相同:
第1步:創建一個新的js文件,並把這個類裏面,我把它叫做xss_ajax.js
var WSAjax = Class.create ({
initialize: function (_url, _callback){
this.url = _url ;
this.callback = _callback ;
this.connect() ;
},
connect: function(){
var script_id = null;
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', this.url);
script.setAttribute('id', 'xss_ajax_script');
script_id = document.getElementById('xss_ajax_script');
if(script_id){
document.getElementsByTagName('head')[0].removeChild(script_id);
}
// Insert <script> into DOM
document.getElementsByTagName('head')[0].appendChild(script);
},
process: function (data){
this.callback(data) ;
}
}) ;
該類創建一個動態腳本元素,其src屬性針對您的JSON數據提供者(實際上,因爲您的遠程服務器必須以此格式提供數據:: call_back_function(// json_data_here)::因此當創建腳本標記時你的JSON將作爲一個函數被直接撤銷(我們將在第2步中討論將回調方法名稱傳遞給服務器),其背後的主要概念是像img元素這樣的腳本不受SOP約束的影響。
第二步:在任何HTML頁面,你想拉JSON異步(我們稱之爲〜AJAJ異步JavaScript + JSON :-),而不是AJAX其使用XHTTPRequest對象)不喜歡下面
//load Prototype first
//load the file you've created in step1
var xss_crawler = new WSAjax (
"http://your_json_data_provider_url?callback=xss_crawler.process"
, function (_data){
// your json data is _data and do whatever you like with it
}) ;
d '你在第1步回覆回調?所以我們將它傳遞給服務器,它將返回嵌入在該方法中的JSON,所以在我們的例子中,服務器將返回一個可消除的JavaScript代碼xss_crawler.process(// the_json_data),請記住,xss_crawler是WSAjax類的一個實例。服務器代碼取決於你(如果它是你的),但是大部分Ajax數據提供者都允許你像參數那樣在參數中指定回調方法。 在Ruby on Rails的我只是做了
render :json=>MyModel.all(:limit=>10), :callback => params[:callback],:content_type => "application/json"
,這一切,現在你可以從你的應用程序(小工具,地圖等),只JSON格式拉從另一個域數據,不要忘記。
我希望這是有益的,感謝您的耐心:-),和平,對不起碼格式,它不能很好地工作
您可以使用YQL的要求去做,而不需要舉辦自己的代理。我做了一個簡單的功能,使其更易於運行命令:
function RunYQL(command, callback){
callback_name = "__YQL_callback_"+(new Date()).getTime();
window[callback_name] = callback;
a = document.createElement('script');
a.src = "http://query.yahooapis.com/v1/public/yql?q="
+escape(command)+"&format=json&callback="+callback_name;
a.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(a);
}
如果您有jQuery的,你可以使用$ .getJSON代替。
樣品可以是這樣的:
RunYQL('select * from html where url="http://www.google.com/"',
function(data){/* actions */}
);
這裏是你如何能做到這一個簡單的方法,而不必使用任何幻想,甚至是JSON。
首先,創建一個服務器端腳本來處理您的請求。喜歡的東西http://www.example.com/path/handler.php
您將參數調用它,是這樣的:.../handler.php參數1 = 12345 &參數2 = 67890
它裏面,處理收到數據後,輸出:
現在document.serverResponse('..all the data, in any format that suits you..');
// Any code could be used instead, because you dont have to encode this data
// All your output will simply be executed as normal javascript
,在客戶端腳本,使用以下命令:
document.serverResponse = function(param){ console.log(param) }
var script = document.createElement('script');
script.src='http://www.example.com/path/handler.php?param1=12345¶m2=67890';
document.head.appendChild(script);
此方法的唯一限制是您可以發送給服務器的參數的最大長度。但是,您始終可以發送多個請求。
如果您使用的是PHP腳本來從遠程服務器的應答,在開始時加入這一行:
header("Access-Control-Allow-Origin: *");
您可以使用該技術CORS配置兩臺服務器(服務器,其中的Javascript運行和外部API服務器)
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
PS:答案https://stackoverflow.com/a/37384641/6505594也是在暗示這種做法,它的開放外部API服務器到其他人來調用它。
而且要非常清楚,這樣的代理是一個嚴重的安全漏洞......至少要列出可接受的地址,不要盲目接受任何通過的地址。 看看一個體面的代理腳本在這裏:http://benalman.com/projects/php-simple-proxy/ – 2010-08-27 14:41:31
但是,當目標頁面有非絕對URL和相對鏈接時,它不會破壞佈局嗎? – Mori 2013-11-29 06:47:46
@ChristianStuder爲什麼這有問題? – John 2016-05-23 07:12:32