AJAX(XMLHttpRequest)进行跨域请求方法详解_第1页
AJAX(XMLHttpRequest)进行跨域请求方法详解_第2页
AJAX(XMLHttpRequest)进行跨域请求方法详解_第3页
AJAX(XMLHttpRequest)进行跨域请求方法详解_第4页
AJAX(XMLHttpRequest)进行跨域请求方法详解_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、注意:以下代码请在Firefox 3.5、Chrome 3.0、Safari 4之后的版本中进行测试。IE8的实现方法与其他浏览不同。 跨域请求,顾名思义,就是一个站点中的资源去访问另外一个不同域名站点上的资源。这种情况很常见,比如说通过 style 标签加载外部样式表文件、通过 img 标签加载外部图片、通过 script 标签加载外部脚本文件、通过 Webfont 加载字体文件等等。默认情况下,脚本访问文档属性等数据采用的是同源策略(Same origin policy)。那么,什么是同源策略呢?如果两个页面的协议、域名和端口是完全相同的,那么它们就是同源的。同源策略是为了防止从一个地址加

2、载的文档或脚本访问或者设置从另外一个地址加载的文档的属性。如果两个页面的主域名相同,则还可以通过设置 document.domain 属性将它们认为是同源的。随着 Web2.0 和 SNS 的兴起,Web 应用对跨域访问的需求也越来越多,但是,在脚本中进行跨域请求是受安全性限制的,Web 开发人员迫切需要提供一种更安全、方便的跨域请求方式来融合(Mashup)自己的 Web 应用。这样做的一个好处就是可以将请求分摊到不同的服务器,减轻单个服务器压力以提高响应速度;另外一个好处是可以将不同的业务逻辑分布到不同的服务器上以降低负载。Cross-Origin Resource Sharing 的工作

3、方式是通过添加 HTTP 头的方法来判断哪些资源允许 Web 浏览器访问该域名下的信息。然而,对于那些 HTTP 请求导致用户数据产生副作用的请求方法(特别是对于除了GET、某些 MIME 类型的 POST 之外的 HTTP方法),该规范要求浏览器对请求进行“预先验”,通过发送 HTTP 的 OPTIONS 请求头询问服务器有哪些支持的方法,在征得服务器的同意后,再使用实际的 HTTP 请求方法发送实际的请求。服务器也可以通知客户端是否需要将验证信息(如 Cookie 和 HTTP Authentication 数据)随同请求一起发送。下面我们就采用实际的例子说明 Cross-Origin R

4、esource Sharing 是如何工作的。1,简单请求 什么样的请求算是简单请求呢?简单请求必须满足下面2点:a,只使用 GET、POST 进行的请求,这里的POST只包括发送给服务器的数据类型(Content-Type)必须是 application/x-www-form-urlencoded、multipart/form-data 或者 text/plain中一个。b,HTTP 请求没有设置自定义的请求头,如我们常用的 X-JSON。先使用下面的代码进行测试:<!DOCTYPE html PUBLIC "-/W3C/DTD XHT

5、ML 1.0 Transitional/EN"    "/TR/xhtml1/DTD/xhtml1-transitional.dtd">  <html xmlns="/1999/xhtml">  <head>    <title>孟宪会之AJAX跨域请求测试</title> 

6、60;</head>  <body>    <input type='button' value='开始测试' onclick='crossDomainRequest()' />    <div id="content"></div>    <mce:script 

7、type="text/javascript"><!-       var xhr = new XMLHttpRequest();       var url = 'http:/dotnet.aspx.cc/SimpleCrossSiteRequests.aspx'       function

8、0;crossDomainRequest()          document.getElementById("content").innerHTML = "开始"         if (xhr)            xhr.open('

9、;GET', url, true);           xhr.onreadystatechange = handler;           xhr.send();          else      &#

10、160;     document.getElementById("content").innerHTML = "不能创建 XMLHttpRequest"                       function handler(evtXHR)  

11、0;       if (xhr.readyState = 4)            if (xhr.status = 200)              var response = xhr.re

12、sponseText;             document.getElementById("content").innerHTML = "结果:" + response;            else       

13、0;      document.getElementById("content").innerHTML = "不允许跨域请求。"                             else   

14、;         document.getElementById("content").innerHTML += "<br/>执行状态 readyState:" + xhr.readyState;                   / 

15、;-></mce:script>  </body>  </html> 然后,在服务器创建 CrossDomainRequest.aspx 的内容如下:<% Page Language="C#" %>  <mce:script runat="server"><!-     protected void Page_Loa

16、d(object sender, EventArgs e)            Response.AddHeader("Access-Control-Allow-Origin", "http:/www.meng_xian_:801");       Response.Write("孟宪会向各位朋友发来贺电:你的第一个跨域测试成功啦!")

17、;        / -></mce:script>点击 “开始测试” 按钮,发送的请求和返回的响应信息如下:1. GET /SimpleCrossSiteRequests.aspx HTTP/1.1    2. Host: dotnet.aspx.cc    3. User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.2; 

18、;zh-CN; rv:) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.5.30729)    4. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8    5. Accept-Language: zh-cn,zh;q=0.5    6. Accept-Encoding: gzip,deflate 

19、60;  7. Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7    8. Keep-Alive: 300    9. Connection: keep-alive    10. Referer: http:/www.meng_xian_:801/CrossDomainAjax/SimpleCrossSiteRequests.html    11. Origin: http:/www.meng_xian_:801 &#

20、160;  12. HTTP/1.x 200 OK    13. Date: Sun, 10 Jan 2010 13:52:00 GMT    14. Server: Microsoft-IIS/6.0    15. X-Powered-By: ASP.NET    16. X-AspNet-Version: 2.0.50727    17. Access-Control-Al

21、low-Origin: http:/www.meng_xian_:801    18. Set-Cookie: ASP.NET_SessionId=wk5v5nrs5wbfi4rmpjy2jujb; path=/; HttpOnly    19. Cache-Control: private    20. Content-Type: text/html; charset=utf-8    21. Content-Length: 84&#

22、160; 是不是现在就可以采用 XMLHttpRequest 来请求任意一个网站的数据呢?还是不行的。允许哪些域名可以访问,还需要服务器来设置 Access-Control-Allow-Origin 头来进行授权,具体的代码是:好了,上面我们就完成了一个简单的跨域请求,怎么样?感觉还是不错的吧。下面我们进行一个“预检”请求。2,预检请求 预检请求首先需要向另外一个域名的资源发送一个 HTTP OPTIONS 请求头,其目的就是为了判断实际发送的请求是否是安全的。下面的2种情况需要进行预检:a,不是上面的简单请求,比如使用Content-Type 为 application/xml 或 text

23、/xml 的 POST 请求b,在请求中设置自定义头,比如 X-JSON、X-MENGXIANHUI 等注意:在 iis 里进行测试,必须在“应用程序扩展”里面配置 .aspx 扩展的动作允许 OPTIONS。下面我们举一个预检的请求: 1. <!DOCTYPE html PUBLIC "-/W3C/DTD XHTML 1.0 Transitional/EN"    2.   "/TR/xhtml1/DTD/xhtml

24、1-transitional.dtd">   3. <html xmlns="/1999/xhtml">   4. <head>   5. <title>孟宪会之AJAX跨域请求测试</title>   6. </head>   7. <body>   8.   <input type=

25、9;button' value='开始测试' onclick='crossDomainRequest()' />   9.   <div id="content"></div>   10.   <mce:script type="text/javascript"><!-    11.   var

26、60;xhr = new XMLHttpRequest();    12.   var url = 'http:/dotnet.aspx.cc/PreflightedRequests.aspx'    13.   function crossDomainRequest()     14.     document.getElementById("con

27、tent").innerHTML = "开始进行请求"    15.     if (xhr)     16.       var xml = "<root>测试</root>"    17.       xhr.open('P

28、OST', url, true);    18.       xhr.setRequestHeader("POWERED-BY-MENGXIANHUI", "Approve");    19.       xhr.setRequestHeader("Content-Type", "application/xml"

29、;);    20.       xhr.onreadystatechange = handler;    21.       xhr.send(xml);    22.      else     23.     document.getElementById("co

30、ntent").innerHTML = "不能创建 XMLHttpRequest。"    24.         25.       26.   function handler(evtXHR)     27.     if (xhr.readyState = 4)  

31、0;  28.       if (xhr.status = 200)     29.         var response = xhr.responseText;    30.         document.getElementById("

32、content").innerHTML = "结果:" + response;    31.        else     32.         document.getElementById("content").innerHTML = "不能进行跨越访问。" &

33、#160;  33.           34.         35.     else     36.       document.getElementById("content").innerHTML += "<br/>执行状态 ready

34、State:" + xhr.readyState;    37.         38.       39. / -></mce:script>   40. </body>   41. </html>   上面的例子我们发送 xml 格式的数据,并且,发送一个非标准的HTTP头 POWERED-BY-MENGXIANHUI 来说明服务器

35、端该如何设置响应头的。在服务器端,PreflightedRequests.aspx 的内容如下: 1. <% Page Language="C#" %>   2. <mce:script runat="server"><!-    3.   protected void Page_Load(object sender, EventArgs e)   

36、; 4.       5.     if (Request.HttpMethod.Equals("GET")    6.               7.       Response.Write("这个页面是用来测试跨域 POST 请求的,直接浏览意义不大。

37、");    8.         9.     else if (Request.HttpMethod.Equals("OPTIONS")    10.         11.       /通知客户端允许预检请求。并设置缓存时间    12.   

38、;    Response.ClearContent();    13.       Response.AddHeader("Access-Control-Allow-Origin", "http:/www.meng_xian_:801");    14.       Response.AddHeader("Access-Control-

39、Allow-Methods", "POST, GET, OPTIONS");    15.       Response.AddHeader("Access-Control-Allow-Headers", "POWERED-BY-MENGXIANHUI");    16.       Response.AddHeader(&qu

40、ot;Access-Control-Max-Age", "30");      17.       /此过程无需返回数据    18.       Response.End();          19.         20.  

41、;   else if (Request.HttpMethod.Equals("POST")    21.         22.       if (Request.Headers"Origin".Equals("http:/www.meng_xian_:801")    23.    

42、       24.         System.Xml.XmlDocument doc = new System.Xml.XmlDocument();    25.         doc.Load(Request.InputStream);    26.     

43、    Response.AddHeader("Access-Control-Allow-Origin", "http:/www.meng_xian_:801");    27.         Response.Write("您提交的数据是:<br/><br/>" + Server.HtmlEncode(doc.OuterXml); 

44、0;  28.           29.       else    30.           31.         Response.Write("不允许你的网站请求。");    32.   

45、0;       33.         34.       35. / -></mce:script>  点击“开始测试”按钮,将会执行下面的一系列请求。 1. OPTIONS /PreflightedRequests.aspx HTTP/1.1    2. Host: dotnet.aspx.cc    3. User-Age

46、nt: Mozilla/5.0 (Windows; U; Windows NT 5.2; zh-CN; rv:) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.5.30729)    4. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8    5. Accept-Langu

47、age: zh-cn,zh;q=0.5    6. Accept-Encoding: gzip,deflate    7. Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7    8. Keep-Alive: 300    9. Connection: keep-alive    10. Origin: http:/www.meng_xian_:801    11. Access-

48、Control-Request-Method: POST    12. Access-Control-Request-Headers: powered-by-mengxianhui    13. HTTP/1.x 200 OK    14. Date: Sun, 10 Jan 2010 14:00:34 GMT    15. Server: Microsoft-IIS/6.0    16

49、. X-Powered-By: ASP.NET    17. X-AspNet-Version: 2.0.50727    18. Access-Control-Allow-Origin: http:/www.meng_xian_:801    19. Access-Control-Allow-Methods: POST, GET, OPTIONS    20. Access-Control-Allow-Headers: POWERED-BY-M

50、ENGXIANHUI    21. Access-Control-Max-Age: 30    22. Set-Cookie: ASP.NET_SessionId=5npqri55dl1k1zvij1tlw3re; path=/; HttpOnly    23. Cache-Control: private    24. Content-Length: 0    25. POST /PreflightedRequests.as

51、px HTTP/1.1    26. Host: dotnet.aspx.cc    27. User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.2; zh-CN; rv:) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.5.30729)    28. Accept: text/h

52、tml,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8    29. Accept-Language: zh-cn,zh;q=0.5    30. Accept-Encoding: gzip,deflate    31. Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7    32. Keep-Alive: 300    33. Connection: 

53、;keep-alive    34. POWERED-BY-MENGXIANHUI: Approve    35. Content-Type: application/xml; charset=UTF-8    36. Referer: http:/www.meng_xian_:801/CrossDomainAjax/PreflightedRequests.html    37. Content-Length: 19    38. Origin:

54、 http:/www.meng_xian_:801    39. Pragma: no-cache    40. Cache-Control: no-cache    41. <root>测试</root>   42. HTTP/1.x 200 OK    43. Date: Sun, 10 Jan 2010 14:00:34 GMT    4

55、4. Server: Microsoft-IIS/6.0    45. X-Powered-By: ASP.NET    46. X-AspNet-Version: 2.0.50727    47. Access-Control-Allow-Origin: http:/www.meng_xian_:801    48. Set-Cookie: ASP.NET_SessionId=byvose45zmtbqy45d2a1jf2i; path=/; 

56、HttpOnly    49. Cache-Control: private    50. Content-Type: text/html; charset=utf-8    51. Content-Length: 65  以上的代码反映了预检请求的执行过程:首先发送 OPTIONS 请求头,用来向服务器咨询服务器的更多信息,以便为后续的真实请求做准备。比如是否支持 POST 方法等。值得注意的是:浏览器还发送 Access-Control-Request-Method: POST 和

57、 Access-Control-Request-Headers: powered-by-mengxianhui 请求头。注意:以上过程是第一次请求的时候的过程,如果在 30 秒内重复点击按钮,你可以看不到 OPTIONS 这一过程。则执行过程是这样的: 1. POST /PreflightedRequests.aspx HTTP/1.1    2. Host: dotnet.aspx.cc    3. User-Agent: Mozilla/5.0 (Windows; U; 

58、Windows NT 5.2; zh-CN; rv:) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.5.30729)    4. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8    5. Accept-Language: zh-cn,zh;q=0.5    6. Accept-E

59、ncoding: gzip,deflate    7. Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7    8. Keep-Alive: 300    9. Connection: keep-alive    10. POWERED-BY-MENGXIANHUI: Approve    11. Content-Type: application/xml; charset=UTF-8 &#

60、160;  12. Referer: http:/www.meng_xian_:801/CrossDomainAjax/PreflightedRequests.html    13. Content-Length: 19    14. Origin: http:/www.meng_xian_:801    15. Pragma: no-cache    16. Cache-Control: no-cache    17. <roo

61、t>测试</root>   18. HTTP/1.x 200 OK    19. Date: Sun, 10 Jan 2010 14:06:32 GMT    20. Server: Microsoft-IIS/6.0    21. X-Powered-By: ASP.NET    22. X-AspNet-Version: 2.0.50727   

62、 23. Access-Control-Allow-Origin: http:/www.meng_xian_:801    24. Set-Cookie: ASP.NET_SessionId=qs1c4urxywdbdx55u04pvual; path=/; HttpOnly    25. Cache-Control: private    26. Content-Type: text/html; charset=utf-8    27. Con

63、tent-Length: 65  为什么会这样?细心的童鞋可能注意到了,在服务器端有一行代码 Response.AddHeader("Access-Control-Max-Age", "30"); 它是用来设置预检的有效时间的,单位是秒。这一点要特别注意。3,带验证信息的请求身份验证是Web开发中经常遇到的问题,在跨域请求中,默认情况下是不发送验证信息的。要想发送验证信息,需要进行withCredentials 属性,下面就是一个简单请求的例子: 1. <!DOCTYPE html PUBLIC&#

64、160;"-/W3C/DTD XHTML 1.0 Transitional/EN"    2.  "/TR/xhtml1/DTD/xhtml1-transitional.dtd">   3. <html xmlns="/1999/xhtml">   4. <head>   5.   <ti

65、tle>孟宪会之AJAX跨域请求测试</title>   6. </head>   7. <body>   8.   <input type='button' value='开始测试' onclick='crossDomainRequest()' />   9.   <div id="content"

66、></div>   10.   <mce:script type="text/javascript"><!-    11.     var xhr = new XMLHttpRequest();    12.     var url = 'http:/dotnet.aspx.cc/Request

67、sWithCredentials.aspx'    13.     function crossDomainRequest()     14.       document.getElementById("content").innerHTML = "开始进行请求"    15.       

68、;if (xhr)     16.         xhr.open('GET', url, true);    17.         xhr.onreadystatechange = handler;    18.        

69、 xhr.withCredentials = "true"    19.         xhr.send();    20.        else     21.         document.getElementById("con

70、tent").innerHTML = "不能创建 XMLHttpRequest。"    22.           23.         24.     function handler(evtXHR)     25.       if

71、 (xhr.readyState = 4)     26.         if (xhr.status = 200)     27.           var response = xhr.responseText;    28.  &

72、#160;        document.getElementById("content").innerHTML = "结果:" + response;    29.          else     30.        &

73、#160;  document.getElementById("content").innerHTML += "<br/>执行状态 status:" + xhr.status;    31.             32.           33.   &

74、#160;   else     34.         document.getElementById("content").innerHTML += "<br/>执行状态 readyState:" + xhr.readyState;    35.         

75、  36.         37. / -></mce:script>   38. </body>   39. </html>  点击“开始测试”,我们可以检测到下面的请求执行过程: 1. GET /RequestsWithCredentials.aspx HTTP/1.1    2. Host: dotnet.aspx.cc    3. Use

76、r-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.2; zh-CN; rv:) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.5.30729)    4. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8    5. Accept-

77、Language: zh-cn,zh;q=0.5    6. Accept-Encoding: gzip,deflate    7. Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7    8. Keep-Alive: 300    9. Connection: keep-alive    10. Referer: http:/www.meng_xian_:801/CrossDomainAjax/Re

78、questsWithCredentials.html    11. Origin: http:/www.meng_xian_:801    12. HTTP/1.x 200 OK    13. Date: Sun, 10 Jan 2010 14:12:26 GMT    14. Server: Microsoft-IIS/6.0    15. X-Powered-By: ASP.NET

79、   16. X-AspNet-Version: 2.0.50727    17. Access-Control-Allow-Origin: http:/www.meng_xian_:801    18. Access-Control-Allow-Credentials: true    19. Set-Cookie: ASP.NET_SessionId=fn2zf0zq1cuwgf45fm5fw145; path=/; HttpOnly  &#

80、160; 20. Set-Cookie: visit=1; expires=Sun, 10-Jan-2010 14:12:56 GMT; path=/    21. Cache-Control: no-cache    22. Pragma: no-cache    23. Expires: -1    24. Content-Type: text/html; charset=utf-8  

81、60; 25. Content-Length: 1  从上面的响应中可以看出,Cookie 是会随请求一起发送的。如果我们多次点击测试按钮,则可以看到请求和响应的结果是这样的: 1. GET /RequestsWithCredentials.aspx HTTP/1.1    2. Host: dotnet.aspx.cc    3. User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.2;

82、 zh-CN; rv:) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.5.30729)    4. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8    5. Accept-Language: zh-cn,zh;q=0.5    6. Accept-Encoding: gzip,deflat

83、e    7. Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7    8. Keep-Alive: 300    9. Connection: keep-alive    10. Referer: http:/www.meng_xian_:801/CrossDomainAjax/RequestsWithCredentials.html    11. Origin: http:/www.meng_xian_:8

84、01    12. Cookie: ASP.NET_SessionId=fn2zf0zq1cuwgf45fm5fw145; visit=2   13. HTTP/1.x 200 OK    14. Date: Sun, 10 Jan 2010 14:13:58 GMT    15. Server: Microsoft-IIS/6.0    16. X-Powered-By: A

85、SP.NET    17. X-AspNet-Version: 2.0.50727    18. Access-Control-Allow-Origin: http:/www.meng_xian_:801    19. Access-Control-Allow-Credentials: true    20. Set-Cookie: visit=3; expires=Sun, 10-Jan-2010 14:14:28 GMT; 

86、;path=/    21. Cache-Control: no-cache    22. Pragma: no-cache    23. Expires: -1    24. Content-Type: text/html; charset=utf-8    25. Content-Length: 1    注意 Cookie: ASP.NET_SessionId=fn2zf0zq1cuwgf45fm5f

87、w145; visit=2 这一行,访问计数器已经被一起发送到服务器。4,IE8 中的实现方法 IE8已经开始支持跨域访问资源了,但是,IE8提供的功能还比较简单,可以进行简单的请求,下面是一个使用的例子: 1. <!DOCTYPE html PUBLIC "-/W3C/DTD XHTML 1.0 Transitional/EN"    2.  "/TR/xhtml1/DTD/xhtml1-transitional.dtd&qu

88、ot;>   3. <html xmlns="/1999/xhtml">   4. <head>   5.   <title>孟宪会之AJAX跨域请求测试</title>   6. </head>   7. <body>   8.   <input type='button&

89、#39; value='开始测试' onclick='crossDomainRequest()' />   9.   <div id="content"></div>   10.   <mce:script type="text/javascript"><!-    11.     var

90、 xhr = new XDomainRequest();    12.     var url = 'http:/dotnet.aspx.cc/SimpleCrossSiteRequests.aspx'    13.     function crossDomainRequest()     14.     &#

91、160; document.getElementById("content").innerHTML = "开始"    15.       if (xhr)     16.         xhr.open('GET', url);    17.    

92、     xhr.onload = handler;    18.         xhr.send();    19.        else     20.       document.getElementById("content&

93、quot;).innerHTML = "不能创建 XDomainRequest"    21.           22.         23.     function handler(evtXHR)     24.       document.getElementById("content").innerHTML = "结果:"

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论