跨域問題Cross Site AJAX[轉載]

來源:互聯網
上載者:User

轉載自: http://blog.joycode.com/saucer/archives/2006/10/03/84572.joy

Cross Site AJAX發表於 2006 年 10 月 03 日 由 saucer

一般情形下,為安全起見,瀏覽器不允許你在用戶端通過XMLHttpRequest訪問別的域(參考串連1,2),即使是同一域的子域
也不行,譬如www.joycode.com 到
blog.joycode.com。(你可以通過某些設定來訪問子域,但因為這方法不是很通行,所有就不考慮了,但如果你感興趣,參考串連2。)

但很明顯,在不少情形下,訪問別的網站,擷取別的網站的資訊/服務是非常有用的,特別是在這個Web 2.0時代。

常用的跨站訪問的方法有3種(參考串連3,4):

  1. 在同一域的伺服器端建立一個代理,瀏覽器向該代理網址發送請求,然後該代理向其他域的網址發請求,在擷取回複後,或作處理或按原樣發回到瀏覽器
  2. 使用按需(On-Demand) Javascript 指令碼。在頁面內動態產生新的<script>,將其src屬性指向別的網站的網址,這個網址返回的內容必須是合法的Javascript指令碼,常用的是JSON訊息。
  3. 使用IFRAME。在頁面內嵌或動態產生指向別的網站的IFRAME,然後這2個網頁間可以通過改變對方的anchor hash
    fragment來傳輸訊息。改變一個網頁的anchor hash
    fragment並不會使瀏覽器重新裝載網頁,所以一個網頁的狀態得以保持,而網頁本身則可以通過一個計時器(timer)來察覺自己anchor
    hash的變化,從而相應改變自己的狀態(參考這個文章中提及的Nikhil Kothari的曆史控制項中的方法)。 Julien Couvreur在他的《Cross-document messaging hack》裡描述了一個更複雜的應用情形,
    “….
    For
    example, if you have page A containing an iframe B in a different
    domain,then B can create a new iframe and load it with a url in the same
    domain as A. The url that is loaded doesn’t generate a request to the
    server if it is properly cached and only the fragment identifier is used
    to pass changing information. Page A can now get the DOM handle on the
    new iframe and successfully retrieve the information transmitted in the
    url by B….” (大體這樣,網頁A包含了一個IFRAME B,B的網頁來自一個不同的域。然後B頁可以產生一個IFRAME
    C,把它指向與網頁A同域的某個地址,因為是A與C同域,網頁A可以訪問C裡的資訊,反之亦然。)

ASP.NET AJAX擴充(即Atlas)提供了一個橋(bridge)機制讓你在伺服器端配置來訪問別的網站,並同時支援POX和SOAP這2種協議。想瞭解其中細節,請參考Atlas文檔裡的《Building Mash-ups with “Atlas”》。當然你完全可以自己建立一個web service,通過它來訪問其他網站並返回資訊。

據說,Atlas中的 IFrameExecutor 可以實現跨域的調用,我按照MSDN部落格Federal Developer Weblog的這篇文章《Calling web services hosted outside of your application with “Atlas”》上的步驟試了一下,但在Windows 2003 Server SP1上得到卻是“Access is denied”的錯誤資訊。然後我下載了該文中的項目,實驗的結果仍舊是“Access is denied”。也許需要改動一些瀏覽器中的什麼設定才能成功,但這不是我的目的,我需要一個在普通設定下都能成功的例子。

按需(On-Demand) Javascript指令碼的實現是很簡單的,譬如我有這樣一個網頁,(想測試的話,需要改動其中的網址)

<html>
<head>
<script language="javascript" type="text/javascript">
function loadContent()
{
var s=document.createElement('SCRIPT');
s.src='http://www.anotherdomain.com/TestCrossJS.aspx?f=setDivContent';
document.body.appendChild(s);
}

function setDivContent(v)
{
var dv = document.getElementById("dv");
dv.innerHTML = v;
}
</script>
</head>
<body>
<div id="dv"></div>

<input type="button" value="Click Me" onclick="loadContent()">
</body>
</html>

其中的www.anotherdomain.com/TestCrossJS.aspx是這樣的,

<script language="C#" runat="server">
void Page_Load(object sender, EventArgs e)
{
  string f = Request.QueryString["f"];
  Response.Clear();
  Response.ContentType = "application/x-javascript";
  Response.Write(String.Format(@"
                   {0}('{1}');", 
                   f,
                   DateTime.Now));
  Response.End();
}
</script>

點擊“Click Me”按鈕,產生一個新的script tag,下載對應的 Javascript 指令碼,結束時回調其中的setDivContent(),從而更新網頁上一個div的內容。

IFRAME的方法好像很流行,除了dojo工具包支援外,據微軟的Dare Obasanjo說(參考串連9),Windows Live Contacts Gadget使用了這個方法來擷取Hotmail的address book。最近,Plaxo公司的開發人員 Joseph Smarr在七月的OSCON 2006會議上作了一個題為《Cross-site Ajax: Challenges and Techniques for Building Rich Web 2.0 Mashups》的講座[來源:Kevin Yank--OSCON 2006: Cross-site Ajax],他們將這個方法做成了一個平台,允許夥伴間合作,他們開發的方案叫“The JavaScript Wormhole(蟲洞)”,據說準備將其推廣為一個標準。他講座的PPT可以在這裡下載,裡面對這個方案做了說明,非常值得看一下。

現在將IFRAME的方法簡單示範如下:

1. http://domain1/TestCross.html:

<html>
<head>
<script language="javascript" type="text/javascript">
var url = "http://domain2/TestCross.html"
var oldHash = null;
var timer = null;

function getHash()
{
var hash = window.location.hash;
if ((hash.length >= 1) && (hash.charAt(0) == '#'))
{
hash = hash.substring(1);
}

return hash;
}
function sendRequest()
{
var d = document;
var t = d.getElementById('request');
var f = d.getElementById('alienFrame');
f.src = url + "#" + t.value + "<br/>" + new Date();
}

function setDivHtml(v)
{
var d = document;
var dv = d.getElementById('response');
dv.innerHTML = v;
}

function idle()
{
var newHash = getHash();

if (newHash != oldHash)
{
setDivHtml(newHash);
oldHash = newHash;
}

timer = window.setTimeout(idle, 100);
}

function window.onload()
{
timer = window.setTimeout(idle, 100);
}
</script>
</head>
<body>

請求:<input type="text" id="request"> <input type="button" value="發送" onclick="sendRequest()" /><br/>
回複:<div id="response"></div>

<iframe id="alienFrame" src="http://domain2/TestCross.html"></iframe>

</body>
</html>

2. http://domain2/TestCross.html:

<html>
<head>
<script language="javascript" type="text/javascript">
var url = "http://domain1/TestCross.html"
var oldHash = null;
var timer = null;

function getHash()
{
var hash = window.location.hash;
if ((hash.length >= 1) && (hash.charAt(0) == '#'))
{
hash = hash.substring(1);
}

return hash;
}
function sendRequest()
{
var d = document;
var t = d.getElementById('request');
var f = parent;
//alert(f.document); //試著去掉這個注釋,你會得到“Access is denied”
f.location.href = url + "#" + t.value + "<br/>" + new Date();
}

function setDivHtml(v)
{
var d = document;
var dv = d.getElementById('response');
dv.innerHTML = v;
}

function idle()
{
var newHash = getHash();

if (newHash != oldHash)
{
setDivHtml(newHash);
oldHash = newHash;
}

timer = window.setTimeout(idle, 100);
}

function window.onload()
{
timer = window.setTimeout(idle, 100);
}
</script>
</head>
<body>

請求:<input type="text" id="request"> <input type="button" value="發送" onclick="sendRequest()" /><br/>
回複:<div id="response"></div>

</body>
</html>

兩個網頁基本相同,第一個網頁內嵌一個IFRAME,在點擊“發送”按鈕後,會將文字框裡的內容通過hash
fragment傳給IFRAME。點擊IFRAME裡的“發送”按鈕後,它會將文字框裡的內容通過hash
fragment傳給父視窗。因為是只改動了hash
fragment,瀏覽器不會重新load網頁內容,這裡使用了一個計時器來檢測URL變化,如果變化了,就更新其中一個div的內容 。

這個方法是不是個安全性漏洞?考慮到微軟的Windows Live都在使用這個方法,估計不是,。這個方法是不是很安全?考慮到這個方法只有在2個網站協作的情形才能成功,安全問題好像不是很大,除非其中涉及的網站本身有XSS的問題。

【參考串連】

1. Security Considerations: Dynamic HTML
http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/sec_dhtml.asp

2. About Cross-Frame Scripting and Security
http://msdn.microsoft.com/library/default.asp?url=/workshop/author/om/xframe_scripting_security.asp

3. Cross-Domain Proxy
http://ajaxpatterns.org/Cross-Domain_Proxy

4. Cross Domain XMLHttpRequest using an IFrame Proxy
http://manual.dojotoolkit.org/WikiHome/DojoDotBook/Book75

5. Back Button Support for Atlas UpdatePanels
http://www.nikhilk.net/BackButtonSupport.aspx

6. Cross-document messaging hack
http://blog.monstuff.com/archives/000304.html

7. Building Mash-ups with “Atlas”
http://atlas.asp.net/docs/Walkthroughs/DevScenarios/bridge.aspx

8. Calling web services hosted outside of your application with “Atlas”
http://blogs.msdn.com/federaldev/archive/2006/07/31/684229.aspx

http://www.federaldeveloper.com/Shared%20Documents/Presentations%20by%20Marc%20Schweigert/CallAtlasWebServiceInDifferentProject.zip

9. AJAX Tip: Passing Messages Between iframes
http://www.25hoursaday.com/weblog/PermaLink.aspx?guid=3b03cf9d-b589-4838-806e-64efcc0a1a15

10. OSCON Cross-site Ajax Slides
http://blog.plaxo.com/archives/2006/07/oscon_crosssite.html

http://www.plaxo.com/css/api/Joseph-Smarr-Plaxo-OSCON-2006.ppt

11. OSCON 2006: Cross-site Ajax
http://www.sitepoint.com/blogs/2006/07/28/oscon-2006-cross-site-ajax/

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.