2KB项目,专业的源码交易网站 帮助 收藏 每日签到

AJAX 跨源 HTTP 请求

  • 时间:2019-01-23 18:36 编辑:2KB 来源:2KB.COM 阅读:327
  • 扫一扫,手机访问
  • 分享
摘要:
AJAX 英文原文:AJAX Cross-Origin HTTP request

背景

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

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

  2. 带填充JSON (JSONP).

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

如此等等..

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

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  
 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请求的域,这些强制条件的浏览器才能提交正式的跨域请求, 并在 预检结果缓存” 中缓存请求结果 。

其它翻译版本 (1) 加载中

实现

让我们看一下服务器端代码,例子如下(ASP.NET和PHP)

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等等并不是很实用的方法。

参考资料

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。 2KB翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。


2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务

  • 全部评论(0)
资讯详情页最新发布上方横幅
最新发布的资讯信息
【计算机/互联网|】Nginx出现502错误(2020-01-20 21:02)
【计算机/互联网|】网站运营全智能软手V0.1版发布(2020-01-20 12:16)
【计算机/互联网|】淘宝这是怎么了?(2020-01-19 19:15)
【行业动态|】谷歌关闭小米智能摄像头,因为窃听器显示了陌生人家中的照片(2020-01-15 09:42)
【行业动态|】据报道谷歌新闻终止了数字杂志,退还主动订阅(2020-01-15 09:39)
【行业动态|】康佳将OLED电视带到美国与LG和索尼竞争(2020-01-15 09:38)
【行业动态|】2020年最佳AV接收机(2020-01-15 09:35)
【行业动态|】2020年最佳流媒体设备:Roku,Apple TV,Firebar,Chromecast等(2020-01-15 09:31)
【行业动态|】CES 2020预览:更多的流媒体服务和订阅即将到来(2020-01-08 21:41)
【行业动态|】从埃隆·马斯克到杰夫·贝佐斯,这30位人物定义了2010年代(2020-01-01 15:14)
联系我们

Q Q: 7090832

电话:400-0011-990

邮箱:7090832@qq.com

时间:9:00-23:00

联系客服
商家入住 服务咨询 投拆建议 联系客服
0577-67068160
手机版

扫一扫进手机版
返回顶部