注意:以下代碼請在Firefox 3.5、Chrome 3.0、Safari 4之後的版本中進行測試。IE8的實現方法與其他瀏覽不同。
3,帶驗證資訊的請求
身分識別驗證是Web開發中經常遇到的問題,在跨域請求中,預設情況下是不發送驗證資訊的。要想發送驗證資訊,需要進行withCredentials 屬性,下面就是一個簡單請求的例子:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"<br /> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><br /><html xmlns="http://www.w3.org/1999/xhtml"><br /><head><br /> <title>孟憲會之AJAX跨域請求測試</title><br /></head><br /><body><br /> <input type='button' value='開始測試' onclick='crossDomainRequest()' /><br /> <div id="content"></div><br /> <mce:script type="text/javascript"><!--<br /> var xhr = new XMLHttpRequest();<br /> var url = 'http://dotnet.aspx.cc/RequestsWithCredentials.aspx';<br /> function crossDomainRequest() {<br /> document.getElementById("content").innerHTML = "開始進行請求……";<br /> if (xhr) {<br /> xhr.open('GET', url, true);<br /> xhr.onreadystatechange = handler;<br /> xhr.withCredentials = "true";<br /> xhr.send();<br /> } else {<br /> document.getElementById("content").innerHTML = "不能建立 XMLHttpRequest。";<br /> }<br /> }<br /> function handler(evtXHR) {<br /> if (xhr.readyState == 4) {<br /> if (xhr.status == 200) {<br /> var response = xhr.responseText;<br /> document.getElementById("content").innerHTML = "結果:" + response;<br /> } else {<br /> document.getElementById("content").innerHTML += "<br/>執行狀態 status:" + xhr.status;<br /> }<br /> }<br /> else {<br /> document.getElementById("content").innerHTML += "<br/>執行狀態 readyState:" + xhr.readyState;<br /> }<br /> }<br />// --></mce:script><br /></body><br /></html>
在伺服器端,我編寫如下的代碼,通過 Cookie 記錄按鈕點擊的次數:
<%@ Page Language="C#" %></p><p><mce:script runat="server"><!--<br /> protected void Page_Load(object sender, EventArgs e)<br /> {<br /> if (Request.HttpMethod.Equals("GET"))<br /> {<br /> Response.AddHeader("Access-Control-Allow-Origin", "http://www.meng_xian_hui.com:801");<br /> Response.AddHeader("Access-Control-Allow-Credentials", "true");<br /> Response.Cache.SetCacheability(HttpCacheability.NoCache);<br /> Response.Expires = -1;<br /> int visit = 1;<br /> if (Request.Cookies["visit"] != null)<br /> {<br /> visit = Convert.ToInt32(Request.Cookies["visit"].Value) + 1;<br /> }<br /> HttpCookie cookie = new HttpCookie("visit", visit.ToString());<br /> cookie.Expires = DateTime.Now.AddSeconds(30);<br /> Response.SetCookie(cookie);<br /> Response.Write(visit.ToString());<br /> }<br /> else if (Request.HttpMethod.Equals("OPTIONS"))<br /> {<br /> //可以根據Origin進行更多檢測</p><p> //通知用戶端允許預檢請求。並設定緩衝時間<br /> Response.ClearContent();<br /> Response.AddHeader("Access-Control-Allow-Origin", "http://www.meng_xian_hui.com:801");<br /> Response.AddHeader("Access-Control-Allow-Methods", "GET, OPTIONS");<br /> Response.AddHeader("Access-Control-Allow-Credentials", "true");<br /> Response.AddHeader("Access-Control-Max-Age", "30");<br /> //此過程無需返回資料<br /> Response.End();<br /> }<br /> else<br /> {<br /> Response.StatusCode = 401;<br /> }<br /> }<br />// --></mce:script>
點擊“開始測試”,我們可以檢測到下面的請求執行過程:
GET /RequestsWithCredentials.aspx HTTP/1.1<br />Host: dotnet.aspx.cc<br />User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.2; zh-CN; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.5.30729)<br />Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8<br />Accept-Language: zh-cn,zh;q=0.5<br />Accept-Encoding: gzip,deflate<br />Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7<br />Keep-Alive: 300<br />Connection: keep-alive<br />Referer: http://www.meng_xian_hui.com:801/CrossDomainAjax/RequestsWithCredentials.html<br />Origin: http://www.meng_xian_hui.com:801<br />HTTP/1.x 200 OK<br />Date: Sun, 10 Jan 2010 14:12:26 GMT<br />Server: Microsoft-IIS/6.0<br />X-Powered-By: ASP.NET<br />X-AspNet-Version: 2.0.50727<br />Access-Control-Allow-Origin: http://www.meng_xian_hui.com:801<br />Access-Control-Allow-Credentials: true<br />Set-Cookie: ASP.NET_SessionId=fn2zf0zq1cuwgf45fm5fw145; path=/; HttpOnly<br />Set-Cookie: visit=1; expires=Sun, 10-Jan-2010 14:12:56 GMT; path=/<br />Cache-Control: no-cache<br />Pragma: no-cache<br />Expires: -1<br />Content-Type: text/html; charset=utf-8<br />Content-Length: 1
從上面的響應中可以看出,Cookie 是會隨請求一起發送的。如果我們多次點擊測試按鈕,則可以看到請求和響應的結果是這樣的:
GET /RequestsWithCredentials.aspx HTTP/1.1<br />Host: dotnet.aspx.cc<br />User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.2; zh-CN; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.5.30729)<br />Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8<br />Accept-Language: zh-cn,zh;q=0.5<br />Accept-Encoding: gzip,deflate<br />Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7<br />Keep-Alive: 300<br />Connection: keep-alive<br />Referer: http://www.meng_xian_hui.com:801/CrossDomainAjax/RequestsWithCredentials.html<br />Origin: http://www.meng_xian_hui.com:801<br />Cookie: ASP.NET_SessionId=fn2zf0zq1cuwgf45fm5fw145; visit=2<br />HTTP/1.x 200 OK<br />Date: Sun, 10 Jan 2010 14:13:58 GMT<br />Server: Microsoft-IIS/6.0<br />X-Powered-By: ASP.NET<br />X-AspNet-Version: 2.0.50727<br />Access-Control-Allow-Origin: http://www.meng_xian_hui.com:801<br />Access-Control-Allow-Credentials: true<br />Set-Cookie: visit=3; expires=Sun, 10-Jan-2010 14:14:28 GMT; path=/<br />Cache-Control: no-cache<br />Pragma: no-cache<br />Expires: -1<br />Content-Type: text/html; charset=utf-8<br />Content-Length: 1
注意 Cookie: ASP.NET_SessionId=fn2zf0zq1cuwgf45fm5fw145; visit=2 這一行,訪問計數器已經被一起發送到伺服器。
4,IE8 中的實現方法
IE8已經開始支援跨域訪問資源了,但是,IE8提供的功能還比較簡單,可以進行簡單的請求,下面是一個使用的例子:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"<br /> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><br /><html xmlns="http://www.w3.org/1999/xhtml"><br /><head><br /> <title>孟憲會之AJAX跨域請求測試</title><br /></head><br /><body><br /> <input type='button' value='開始測試' onclick='crossDomainRequest()' /><br /> <div id="content"></div><br /> <mce:script type="text/javascript"><!--<br /> var xhr = new XDomainRequest();<br /> var url = 'http://dotnet.aspx.cc/SimpleCrossSiteRequests.aspx';<br /> function crossDomainRequest() {<br /> document.getElementById("content").innerHTML = "開始……";<br /> if (xhr) {<br /> xhr.open('GET', url);<br /> xhr.onload = handler;<br /> xhr.send();<br /> } else {<br /> document.getElementById("content").innerHTML = "不能建立 XDomainRequest";<br /> }<br /> }<br /> function handler(evtXHR) {<br /> document.getElementById("content").innerHTML = "結果:" + xhr.responseText;<br /> }<br />// --></mce:script><br /></body><br /></html>
另外,IE8的實現方法與其他瀏覽器不同。更多內容請參考 XDomainRequest 對象,地址是:
http://msdn.microsoft.com/zh-cn/library/cc288060(VS.85).aspx
最後,願意測試的朋友可以訪問這個 http://dotnet.aspx.cc/SimpleCrossSiteRequests.aspx 地址進行“簡單請求”的測試,本頁面允許任何地址進行跨域訪問。(不好意思,個人網站可能被河蟹了)