好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

利用iframe实现ajax 跨域通信的解决方案

利用iframe实现ajax 跨域通信的解决方案

 在漫长的前端开发旅途上,无可避免的会接触到ajax,而且一般情况下都是用在同一域下的ajax请求;但是如果请求是发生在不同的域下,请求就无法执行,并且会抛出异常提示不允许跨域请求,目前我没有找到明确的资料说明这是为什么,我觉得应该是出于安全性的考虑吧。纵然如此,要实现跨域访问的话,方法还是有的,而且不只一种,在这里介绍其中一种解决方案:如何利用iframe完成ajax的跨域请求。

  

  如下图所示:域a.com的页面request.html(即http://a.com/request.html)里面嵌套了一个iframe指向域b.com的response.html,而response.html里又嵌套了域a.com的proxy.html。

  要实现域a.com的request.html请求域b.com的process.php,可以将请求的参数通过URL传给response.html,由response.html向process.php发出真正的ajax请求(response.html与process.php都属于域b.com),然后将返回的结果通过URL传给proxy.html,最后由于proxy.html与request.html是在同一域下,所以可以在proxy.html利用window.top将结果返回给request.html完成跨域通信。

  整个流程的思路其实非常清晰,真正的ajax请求并不是发生在域a.com,而是发生在域b.com;而域a.com是做了两件事,第一件事是由request.html完成,向域b.com发送传入参数;第二件事由proxy.html完成,把域b.com的响应数据递回给request.html。

跨域访问流程图

  OK,接下来就是如何用代码实现了;在此之前先看文档结构:

  http://a.com/

    request.html

    proxy.html

  http://b.com/

    response.html

    process.php

1、先来看request.html,为了方便理解,我把js也放到了页面上:

  1   <!  DOCTYPE html  > 
  2   <  html  > 
  3   <  head  > 
  4       <  meta   http-equiv  ="Content-Type"   content  ="text/html; charset=UTF-8"  > 
  5       <  title  > 该页面的路径是:http://a.com/request.html </  title  > 
  6   </  head  > 
  7   <  body  > 
  8       <  p   id  ="result"  > 这里将会填上响应的结果 </  p  > 
  9       <  a   id  ="sendBtn"   href  ="javascript:void(0)"  > 点击,发送跨域请求 </  a  > 
 10       <  iframe   id  ="serverIf"  ></  iframe  > 
 11       <  script   type  ="text/javascript"  > 
 12           document.getElementById(  "  sendBtn  "  ).onclick   =   function  () {
  13               var   url   =   "  http://b.com/response.html  "  ;
  14               var   fn   =   "  GetPerson  "  ; //这是定义在response.html的方法
   15               var   reqdata   =   '  {"id" : 24}  '  ; //这是请求的参数
   16               var   callback   =   "  CallBack  "  ; //这是请求全过程完成后执行的回调函数,执行最后的动作
   17               CrossRequest(url, fn, reqdata, callback); //发送请求
   18           }
  19           function   CrossRequest(url, fn, reqdata, callback) {
  20               var   server   =   document.getElementById(  "  serverIf  "  );
  21               server.src   =   url   +   "  ?fn=  "   +   encodeURIComponent(fn)   +   "  &data=  "   +   encodeURIComponent(reqdata)   +   "  &callback=  "   +   encodeURIComponent(callback); //这里由request.html向response.html发送的请求其实就是通过iframe的src将参数与回调方法传给response.html
   22           }
  23           function   CallBack(data) { //回调函数
   24               var   str   =   "  My name is   "   +   data.name   +   "  . I am a   "   +   data.sex   +   "  . I am   "   +   data.age   +   "   years old.  "  ;
  25               document.getElementById(  "  result  "  ).innerHTML   =   str;
  26           }
  27       </  script  > 
 28   </  body  > 
 29   </  html  > 

  看代码和注释相信都很容易理解,这个页面其实就是要告诉response.html:我要让你执行你定义好的方法GetPerson,并且要用我给你的参数'{"id" : 24}'。可能感到模糊的就是为什么要把CallBack函数传给response.html,这是定义在本页面上的方法,response.html也不能执行它;看接下来的代码就会知道:response.html纯粹是负责将CallBack这个方法名传递给下一位仁兄proxy.html,而proxy.html拿到了CallBack这个方法名就可以执行了,因为proxy.html和request.html是同域的。

2、接下来我们看response.html的代码:

  1   <!  DOCTYPE html  > 
  2   <  html  > 
  3   <  head  > 
  4   <  meta   http-equiv  ="Content-Type"   content  ="text/html; charset=UTF-8"  > 
  5   <  title  > 该页面的路径是:http://b.com/response.html </  title  > 
  6   </  head  > 
  7   <  body  > 
  8       <  iframe   id  ="proxy"  ></  iframe  > 
  9       <  script   type  ="text/javascript"  > 
 10           function   _request(reqdata, url, callback) { //通用方法,ajax请求
   11               var   xmlhttp;
  12               if   (window.XMLHttpRequest) {
  13                   xmlhttp   =   new   XMLHttpRequest();
  14               }
  15               else   {
  16                   xmlhttp   =   new   ActiveXObject(  "  Microsoft.XMLHTTP  "  );
  17               }
  18               xmlhttp.onreadystatechange   =   function   () {
  19                   if   (xmlhttp.readyState   ==   4   &&   xmlhttp.status   ==   200  ) {
  20                       var   data   =   xmlhttp.responseText;
  21                       callback(data);
  22                   }
  23               }
  24               xmlhttp.open(  "  POST  "  , url);
  25               xmlhttp.setRequestHeader(  "  Content-Type  "  ,   "  application/json; charset=utf-8  "  );
  26               xmlhttp.send(reqdata);
  27           }
  28           function   _getQuery(key) { //通用方法,获取url参数
   29               var   query   =   location.href.split(  "  ?  "  )[  1  ];
  30               var   value   =   decodeURIComponent(query.split(key   +   "  =  "  )[  1  ].split(  "  &  "  )[  0  ]);
  31               return   value;
  32           }
  33           function   GetPerson(reqdata, callback) { //向process.php发送ajax请求
   34               var   url   =   "process  .php  "  ;
  35               var   fn   =   function  (data) {
  36                   var   proxy   =   document.getElementById(  "  proxy  "  );
  37                   proxy.src   =   "  http://b.com/Proxy.html?data=  "   +   encodeURIComponent(data)   +   "  &callback=  "   +   encodeURIComponent(callback);
  38               }
  39               _request(reqdata, url, fn);
  40           }
  41           (  function  () {
  42               var   fn   =   _getQuery(  "  fn  "  );
  43               var   reqdata   =   _getQuery(  "  data  "  );
  44               var   callback   =   _getQuery(  "  callback  "  );
  45               eval(fn   +   "  ('  "   +   reqdata   +  "  ', '  "   +   callback   +   "  ')  "  );
  46           })();
  47       </  script  > 
 48   </  body  > 
 49   </  html  > 

   这里其实就是接收来自request.html的请求得到请求参数和方法后向服务器process.php发出真正的ajax请求,然后将从服务器返回的数据以及从request.html传过来的回调函数名传递给proxy.html。

3、接下来看一下process.php的代码,比较简单:

 1  <? php 
  2   $data  = json_decode( file_get_contents ("php://input" ));
  3   header ("Content-Type: application/json; charset=utf-8" );
  4   echo  ('{"id" : ' .  $data ->id . ', "age" : 24, "sex" : "boy", "name" : "huangxueming"}' );
  5  ?>

这几句代码就不打算讲了,稍微有点PHP基础都能看懂,没PHP基础的应该都能看出个大概了,呵呵~~~

4、最后就是proxy.html了:

  1   <!  DOCTYPE html  > 
  2   <  html  > 
  3   <  head  > 
  4       <  meta   http-equiv  ="Content-Type"   content  ="text/html; charset=UTF-8"  > 
  5       <  title  > 该页面的路径是:http://a.com/proxy.html </  title  > 
  6   </  head  > 
  7   <  body  > 
  8       <  script   type  ="text/javascript"  > 
  9           function   _getUrl(key) { //通用方法,获取URL参数
   10               var   query   =   location.href.split(  "  ?  "  )[  1  ];
  11               var   value   =   decodeURIComponent(query.split(key   +   "  =  "  )[  1  ].split(  "  &  "  )[  0  ]);
  12               return   value;
  13           }
  14           (  function  () {
  15               var   callback   =   _getUrl(  "  callback  "  );
  16               var   data   =   _getUrl(  "  data  "  );
  17               eval(  "  window.top.  "   +   decodeURIComponent(callback)   +   "  (  "   +   decodeURIComponent(data)   +   "  )  "  );
  18           })()
  19       </  script  > 
 20   </  body  > 
 21   </  html  > 

  这里也是最后一步了,proxy终于拿到了request.html透过response.html传过来的回调函数名以及从response.html直接传过来的响应数据,利用window.top执行request.html里定义的回调函数。

  实际应用中,proxy.html基本上可以是一个通用的代理,无需改动,如果需要用到很多跨域方法,这些方法都可以在域a.com里面加上,而域b.com就相当于定义一些接口供a.com调用,如GetPerson,当然这并不是真正的接口,只是方便理解,打个比方;另外,当然就是要把iframe隐藏起来。OK,最后还是奉上那句老话:所拥有的技术并不是最重要的,最重要的是学习的能力。

  

 

 

 

标签:  js ,  ajax ,  跨域

http://www.cnblogs.com/xueming/archive/2013/02/01/CrossDomainAjax.html

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于利用iframe实现ajax 跨域通信的解决方案的详细内容...

  阅读:32次

上一篇: 浅谈 XSS & CSRF

下一篇:Ajax简单聊天B/S