• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

AJAX 跨源 HTTP 请求

相关文章 搞代码 7年前 (2018-06-22) 188次浏览 已收录 0个评论
文章目录[隐藏]

 背景

  跨源HTTP请求(也称跨域AJAX请求)是大多数web开发人员可能遇到的一个问题,根据同源策略,浏览器将限制客户端的JavaScript在一个安全沙箱内,通常js不能直接同一台不同的域的远程服务器通信。在过去,开发者们创造了许多解决方法以实现跨域资源请求,常用的方法如下:

  1. 使用Flash/Silverlight或服务器端“代理”来与远程通讯 

  2. 带填充JSON (JSONP).

  3. 在iframe中嵌入远程服务器并通过fragment或window.name通信,参考这里。

  如此等等..

  这些解决方法或多或少都有问题,比如使用JSONP时若只是简单的“eval”将导致安全漏洞,#3虽然能用,但两个域间必须依据严格的协议,恕我直言它既不灵活也不优雅

  W3C已经引入了跨域资源共享 (CORS)作为能够解决该问题并提供安全、灵活以及推荐标准的解决方案。

 机制

  从较高的层次来看我们可以简单认为CORS 是介于 域A客户端 的AJAX调用 和一个托管在域B的页面 之间的契约, 一个典型的跨源 请求或者响应将会是这样:

  域 A 的 AJAX 请求头

Host DomainB.com  
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0  
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/json  
Accept-Language en-us;  
Accept-Encoding gzip, deflate  
Keep-Alive 115  

http://www.gaodaima.com/?p=59088AJAX 跨源 HTTP 请求

 Origin http://DomainA.com

  域 B 的 响应头

Cache-Control private /> Content-Type application/json; charset=utf-8  
 access-Control-Allow-Origin DomainA.com  
Content-Length 87  
Proxy-Connection Keep-Alive  
Connection Keep-Alive

  我上面标记的蓝色部分是关键实现, "Origin" 请求头表示  跨源请求 或者 预检请求 源于哪里,  "Access-Control-Allow-Origin" 请求头 表示这个页面允许来自域A 的请求(其值为 * 表示允许任何域的远程请求)。

  像我上面提到的,W3 建议浏览器在提交实际跨源HTTP 请求前,实现“预检请求”, 简而言之,就是一个HTTP OPTIONS 请求:

OPTIONS DomainB.com/foo.aspx HTTP/1.1

  如果 foo.aspx 支持 OPTIONS HTTP 指令, 它可能会像下面这样返回响应:

HTTP/1.1 200 OK  
Date: Wed, 01 Mar 2011 15:38:19 GMT  
Access-Control-Allow-Origin:   http://DomainB.com  
Access-Control-Allow-Methods: POST, GET, OPTIONS, HEAD  
Access-Control-Allow-Headers: X-Requested-With  
Access-Control-Max-Age: 1728000  
Connection: Keep-Alive  
Content-Type: application/json

  只有满足在响应中包含 "Access-Control-Allow-Origin" , 并且其值为 "*" 或者包含提交CORS请求的域,这些强制条件的浏览器才能提交正式的跨域请求, 并在 预检结果缓存” 中缓存请求结果 。

 实现

  让我们看一下服务器端代码,例子如下(asp.netphp

  ASP.NET (c#)

 protected void Page_Load(object sender, EventArgs e)  {      String data = String.Empty;      String returnJSONStr = String.Empty;        switch (Request.HttpMethod)      {          case "GET":              data = Request.QueryString["Data"];              returnJSONStr = "{/"Data/":/"Hi remote friend, you tried to passed me data: *" + data + "* through HTTP GET./"}";              break;          case "POST":              data = Request.Form["Data"];              returnJSONStr = "{/"Data/":/"Hi remote friend, you tried to POST some mock data: *" + data + "* to me./"}";              break;          case "OPTIONS":              break;          default:              returnBadRequestResponse();              break;      }        if (String.IsNullOrEmpty(data))          returnBadRequestResponse();      else      {          Response.AddHeader("Access-Control-Allow-Origin", "*");          Response.ContentType = "application/json";          Response.Write(returnJSONStr);      }  }    private void returnBadRequestResponse()  {      Response.StatusCode = 400;      Response.ContentType = "application/json";      Response.Write("{/"Error/":/"Bad HTTP request type!/"}");  } 

  PHP

 

 if(isset($["Data"]))   {       $method=$_SERVER['REQUEST_METHOD'];       $data="";       if($method=="POST")       {           $data=$_POST["Data"];             $fakeData=new FakeData();           $fakeData->Data="Hi remote friend, you tried to POST some mock data: *"+data+"* to me.";           $fakeData->Time=new DateTime("now");       }       elseif($method=="GET")       {           $fakeData=new FakeData();           $fakeData->Data="Hi remote friend, you tried to passed me data: *"+data+"* through HTTP GET.";           $fakeData->Time=new DateTime("now");       }       else       {           RaiseError();       }         header('Content-type: application/json');       $jsonStr= json_encode($fakeData);       echo($jsonStr);   }   else   {       RaiseError();   }     function RaiseError()   {       http_send_status(405);       header("Status: 405 Method Not Allowed");   }     /*Classes definition*/   class FakeData   {       public $Data;       public $Time;   } 

  客户端AJAXY发起请求代码:

 

 var cor = null; // cor stands for Cross-Origin request    if (window.XMLHttpRequest) {      cor = new XMLHttpRequest();  }  //else if (window.XDomainRequest) {      //cor = new XDomainRequest();  //}  else {      alert("Your browser does not support Cross-Origin request!");      return;  }    cor.onreadystatechange = function () {      if (cor.readyState == 4) {          document.getElementById('lbl').innerHTML = cor.responseText;      }  };    var data = 'Some fake data';  if (method == 'POST') {      cor.open('POST', 'http://WayneYe.com/Demo/CORSDemo/CORSDemoServer.aspx', true);      cor.withCredential = "true";      cor.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');      cor.send('Data=' + data);  }  else if (method == 'GET') {       cor.open('GET', 'http://WayneYe.com/Demo/CORSDemo/CORSDemoServer.aspx?Data=' + data, true);      cor.withCredential = "true";      cor.send(null);  } 

  JS代码适用于所有主流浏览器(IE8+, FF 3.6+, Chrome 8+),我没有用IE8所采用的XDomainObject,因为 IE8+, FF and Chrome, Safari等浏览器支持XMLHTTP请求。而且XDomainObject(XDR)似乎有很多限制(参考: http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx)

 结论

  跨源资源共享为网站开发人员实现跨源通信提供了一个安全,灵活,标准的方案。也许是时候摈弃像JSONP,Flash,Silverlight,server bridge以及window.name等等并不是很实用的方法。

 参考资料

  原文地址:http://www.codeproject.com/Articles/185506/AJAX-Cross-Origin-HTTP-request

欢迎大家阅读《AJAX 跨源 HTTP 请求》,跪求各位点评,若觉得好的话请收藏本文,by 搞代码


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:AJAX 跨源 HTTP 请求

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址