JavaScript使ifram跨域相互访问及与PHP通信的实例


Posted in Javascript onMarch 03, 2016

iframe 与主框架相互访问方法

1.同域相互访问

假设A.html 与 b.html domain都是localhost (同域)
A.html中iframe 嵌入 B.html,name=myframe
A.html有js function fMain()
B.html有js function fIframe()
需要实现 A.html 调用 B.html 的 fIframe(),B.html 调用 A.html 的 fMain()

A.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
 <head> 
 <meta http-equiv="content-type" content="text/html; charset=utf-8"> 
 <title> main window </title> 
 
 <script type="text/javascript"> 
 // main js function 
 function fMain(){ 
 alert('main function execute success'); 
 } 
 
 // exec iframe function 
 function exec_iframe(){ 
 window.myframe.fIframe(); 
 } 
 </script> 
 
 </head> 
 
 <body> 
 <p>A.html main</p> 
 <p><input type="button" value="exec iframe function" onclick="exec_iframe()"></p> 
 <iframe src="B.html" name="myframe" width="500" height="100"></iframe> 
 </body> 
</html>

B.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
 <head> 
 <meta http-equiv="content-type" content="text/html; charset=utf-8"> 
 <title> iframe window </title> 
 
 <script type="text/javascript"> 
 // iframe js function 
 function fIframe(){ 
 alert('iframe function execute success'); 
 } 
 
 // exec main function 
 function exec_main(){ 
 parent.fMain(); 
 } 
 </script> 
 
 </head> 
 
 <body> 
 <p>B.html iframe</p> 
 <p><input type="button" value="exec main function" onclick="exec_main()"></p> 
 </body> 
</html>

点击A.html 的 exec iframe function button,执行成功,弹出iframe function execute success。如下图

JavaScript使ifram跨域相互访问及与PHP通信的实例

点击B.html 的 exec main function button,执行成功,弹出 main function execute success。如下图

JavaScript使ifram跨域相互访问及与PHP通信的实例

2.跨域互相访问

假设 A.html domain是 localhost, B.html domain 是 127.0.0.1 (跨域)
这里使用 localhost 与 127.0.0.1 只是方便测试,localhost 与 127.0.0.1已经不同一个域,因此执行效果是一样的。
实际使用时换成 www.domaina.com 与 www.domainb.com 即可。
A.html中iframe 嵌入 B.html,name=myframe
A.html有js function fMain()
B.html有js function fIframe()
需要实现 A.html 调用 B.html 的 fIframe(),B.html 调用 A.html 的 fMain() (跨域调用)

如果使用上面同域的方法,浏览器判断A.html 与 B.html 不同域,会有错误提示。
Uncaught SecurityError: Blocked a frame with origin "http://localhost" from accessing a frame with origin "http://127.0.0.1". Protocols, domains, and ports must match.

实现原理:
因为浏览器为了安全,禁止了不同域访问。因此只要调用与执行的双方是同域则可以相互访问。

首先,A.html 如何调用B.html的 fIframe方法
1.在A.html 创建一个 iframe
2.iframe的页面放在 B.html 同域下,命名为execB.html
3.execB.html 里有调用B.html fIframe方法的js调用

<script type="text/javascript"> 
parent.window.myframe.fIframe(); // execute parent myframe fIframe function 
</script>

这样A.html 就能通过 execB.html 调用 B.html 的 fIframe 方法了。

同理,B.html 需要调用A.html fMain方法,需要在B.html 嵌入与A.html 同域的 execA.html
execA.html 里有调用 A.html fMain 方法的js 调用

<script type="text/javascript"> 
parent.parent.fMain(); // execute main function 
</script>

这样就能实现 A.html 与 B.html 跨域相互调用。

A.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
 <head> 
 <meta http-equiv="content-type" content="text/html; charset=utf-8"> 
 <title> main window </title> 
 
 <script type="text/javascript"> 
 
 // main js function 
 function fMain(){ 
 alert('main function execute success'); 
 } 
 
 // exec iframe function 
 function exec_iframe(){ 
 if(typeof(exec_obj)=='undefined'){ 
  exec_obj = document.createElement('iframe'); 
  exec_obj.name = 'tmp_frame'; 
  exec_obj.src = 'http://127.0.0.1/execB.html'; 
  exec_obj.style.display = 'none'; 
  document.body.appendChild(exec_obj); 
 }else{ 
  exec_obj.src = 'http://127.0.0.1/execB.html?' + Math.random(); 
 } 
 } 
 </script> 
 
 </head> 
 
 <body> 
 <p>A.html main</p> 
 <p><input type="button" value="exec iframe function" onclick="exec_iframe()"></p> 
 <iframe src="http://127.0.0.1/B.html" name="myframe" width="500" height="100"></iframe> 
 </body> 
</html>

B.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
 <head> 
 <meta http-equiv="content-type" content="text/html; charset=utf-8"> 
 <title> iframe window </title> 
 
 <script type="text/javascript"> 
 // iframe js function 
 function fIframe(){ 
 alert('iframe function execute success'); 
 } 
 
 // exec main function 
 function exec_main(){ 
 if(typeof(exec_obj)=='undefined'){ 
  exec_obj = document.createElement('iframe'); 
  exec_obj.name = 'tmp_frame'; 
  exec_obj.src = 'http://localhost/execA.html'; 
  exec_obj.style.display = 'none'; 
  document.body.appendChild(exec_obj); 
 }else{ 
  exec_obj.src = 'http://localhost/execA.html?' + Math.random(); 
 } 
 } 
 </script> 
 
 </head> 
 
 <body> 
 <p>B.html iframe</p> 
 <p><input type="button" value="exec main function" onclick="exec_main()"></p> 
 </body> 
</html>

execA.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
 <head> 
 <meta http-equiv="content-type" content="text/html; charset=utf-8"> 
 <title> exec main function </title> 
 </head> 
 
 <body> 
 <script type="text/javascript"> 
  parent.parent.fMain(); // execute main function 
 </script> 
 </body> 
</html>

execB.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
 <head> 
 <meta http-equiv="content-type" content="text/html; charset=utf-8"> 
 <title> exec iframe function </title> 
 </head> 
 
 <body> 
 <script type="text/javascript"> 
  parent.window.myframe.fIframe(); // execute parent myframe fIframe function 
 </script> 
 </body> 
</html>

执行如下图:

JavaScript使ifram跨域相互访问及与PHP通信的实例

php main 与 iframe 相互通讯类(同域/跨域)
把main与iframe相互通讯的方法封装成类,主要有两个文件,
JS:FrameMessage.js 实现调用方法的接口,如跨域则创建临时iframe,调用同域执行者。
PHP:FrameMessage.class.php 实现接收到跨域请求时,根据参数返回执行方法的JS code。

功能如下:
1.支持同域与跨域通讯
2.传递的方法参数支持字符串,JSON,数组等。

JavaScript使ifram跨域相互访问及与PHP通信的实例

FrameMessage.exec('http://127.0.0.1/execB.php', 'myframe', 'fIframe', ['fdipzone', '{"gender":"male","age":"29"}', '["http://blog.csdn.net/fdipzone", "http://weibo.com/fdipzone"]']); 

JavaScript使ifram跨域相互访问及与PHP通信的实例

FrameMessage.exec('http://localhost/execA.php', '', 'fMain', ['programmer', '{"first":"PHP","second":"javascript"}', '["EEG","NMG"]']);

FrameMessage.js

/** Main 与 Iframe 相互通讯类 支持同域与跨域通讯 
* Date: 2013-12-29 
* Author: fdipzone 
* Ver: 1.0 
*/ 
var FrameMessage = (function(){ 
 
 this.oFrameMessageExec = null; // 临时iframe 
 
 /* 执行方法 
 executor 执行的页面,为空则为同域 
 frame 要调用的方法的框架名称,为空则为parent 
 func  要调用的方法名 
 args  要调用的方法的参数,必须为数组[arg1, arg2, arg3, argn...],方便apply调用 
    元素为字符串格式,请不要使用html,考虑注入安全的问题会过滤 
 */ 
 this.exec = function(executor, frame, func, args){ 
 
  this.executor = typeof(executor)!='undefined'? executor : ''; 
  this.frame = typeof(frame)!='undefined'? frame : ''; 
  this.func = typeof(func)!='undefined'? func : ''; 
  this.args = typeof(args)!='undefined'? (__fIsArray(args)? args : []) : []; // 必须是数组 
 
  if(executor==''){ 
   __fSameDomainExec(); // same domain 
  }else{ 
   __fCrossDomainExec(); // cross domain 
  } 
 
 } 
 
 /* 同域执行 */ 
 function __fSameDomainExec(){ 
  if(this.frame==''){ // parent 
   parent.window[this.func].apply(this, this.args); 
  }else{ 
   window.frames[this.frame][this.func].apply(this, this.args); 
  } 
 } 
 
 /* 跨域执行 */ 
 function __fCrossDomainExec(){ 
  if(this.oFrameMessageExec == null){ 
   this.oFrameMessageExec = document.createElement('iframe'); 
   this.oFrameMessageExec.name = 'FrameMessage_tmp_frame'; 
   this.oFrameMessageExec.src = __fGetSrc(); 
   this.oFrameMessageExec.style.display = 'none'; 
   document.body.appendChild(this.oFrameMessageExec); 
  }else{ 
   this.oFrameMessageExec.src = __fGetSrc(); 
  } 
 } 
 
 /* 获取执行的url */ 
 function __fGetSrc(){ 
  return this.executor + (this.executor.indexOf('?')==-1? '?' : '&') + 'frame=' + this.frame + '&func=' + this.func + '&args=' + JSON.stringify(this.args) + '&framemessage_rand=' + Math.random(); 
 } 
 
 /* 判断是否数组 */ 
 function __fIsArray(obj){ 
  return Object.prototype.toString.call(obj) === '[object Array]'; 
 } 
 
 return this; 
 
}());

FrameMessage.class.php

<?php 
/** Frame Message class main 与 iframe 相互通讯类 
* Date: 2013-12-29 
* Author: fdipzone 
* Ver: 1.0 
* 
* Func: 
* public execute 根据参数调用方法 
* private returnJs 创建返回的javascript 
* private jsFormat 转义参数 
*/ 
 
class FrameMessage{ // class start 
 
 /* execute 根据参数调用方法 
 * @param String $frame 要调用的方法的框架名称,为空则为parent 
 * @param String $func 要调用的方法名 
 * @param JSONstr $args 要调用的方法的参数 
 * @return String 
 */ 
 public static function execute($frame, $func, $args=''){ 
 
  if(!is_string($frame) || !is_string($func) || !is_string($args)){ 
   return ''; 
  } 
 
  // frame 与 func 限制只能是字母数字下划线 
  if(($frame!='' && !preg_match('/^[A-Za-z0-9_]+$/',$frame)) || !preg_match('/^[A-Za-z0-9_]+$/',$func)){ 
   return ''; 
  } 
 
  $params_str = ''; 
 
  if($args){ 
   $params = json_decode($args, true); 
    
   if(is_array($params)){ 
 
    for($i=0,$len=count($params); $i<$len; $i++){ // 过滤参数,防止注入 
     $params[$i] = self::jsFormat($params[$i]); 
    } 
     
    $params_str = "'".implode("','", $params)."'"; 
   } 
  } 
 
  if($frame==''){ // parent 
   return self::returnJs("parent.parent.".$func."(".$params_str.");"); 
  }else{ 
   return self::returnJs("parent.window.".$frame.".".$func."(".$params_str.");"); 
  } 
 
 } 
 
 
 /** 创建返回的javascript 
 * @param String $str 
 * @return String 
 */ 
 private static function returnJs($str){ 
 
  $ret = '<script type="text/javascript">'."\r\n"; 
  $ret .= $str."\r\n"; 
  $ret .= '</script>'; 
 
  return $ret; 
 } 
 
 
 /** 转义参数 
 * @param String $str 
 * @return String 
 */ 
 private static function jsFormat($str){ 
 
  $str = strip_tags(trim($str)); // 过滤html 
  $str = str_replace('\\s\\s', '\\s', $str); 
  $str = str_replace(chr(10), '', $str); 
  $str = str_replace(chr(13), '', $str); 
  $str = str_replace(' ', '', $str); 
  $str = str_replace('\\', '\\\\', $str); 
  $str = str_replace('"', '\\"', $str); 
  $str = str_replace('\\\'', '\\\\\'', $str); 
  $str = str_replace("'", "\'", $str); 
 
  return $str; 
 } 
 
} // class end 
 
?>

A.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
 <head> 
 <meta http-equiv="content-type" content="text/html; charset=utf-8"> 
 <title> main window </title> 
 <script type="text/javascript" src="json2.js"></script> 
 <script type="text/javascript" src="FrameMessage.js"></script> 
 
 <script type="text/javascript"> 
 
 // main js function 
 function fMain(profession, skill, company){ 
 
 var skill_p = JSON.parse(skill); 
 var company_p = JSON.parse(company); 
  
 var msg = "main function execute success\n\n"; 
 msg += "profession:" + profession + "\n"; 
 msg += "first skill:" + skill_p.first + "\n"; 
 msg += "second skill:" + skill_p.second + "\n"; 
 msg += "company1:" + company_p[0] + "\n"; 
 msg += "company2:" + company_p[1] + "\n"; 
 
 alert(msg); 
 
 } 
 
 // exec iframe function 
 function exec_iframe(){ 
 // same domain 
 //FrameMessage.exec('', 'myframe', 'fIframe', ['fdipzone', '{"gender":"male","age":"29"}', '["http://blog.csdn.net/fdipzone", "http://weibo.com/fdipzone"]']); 
 
 // cross domain 
 FrameMessage.exec('http://127.0.0.1/execB.php', 'myframe', 'fIframe', ['fdipzone', '{"gender":"male","age":"29"}', '["http://blog.csdn.net/fdipzone", "http://weibo.com/fdipzone"]']); 
 } 
 </script> 
 
 </head> 
 
 <body> 
 <p>A.html main</p> 
 <p><input type="button" value="exec iframe function" onclick="exec_iframe()"></p> 
 <!-- same domain --> 
 <!--<iframe src="B.html" name="myframe" width="500" height="100"></iframe>--> 
 <!-- cross domain --> 
 <iframe src="http://127.0.0.1/B.html" name="myframe" width="500" height="100"></iframe> 
 </body> 
</html> 


B.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
 <head> 
 <meta http-equiv="content-type" content="text/html; charset=utf-8"> 
 <title> iframe window </title> 
 <script type="text/javascript" src="json2.js"></script> 
 <script type="text/javascript" src="FrameMessage.js"></script> 
 
 <script type="text/javascript"> 
 
 // iframe js function 
 function fIframe(name, obj, arr){ 
  
 var obj_p = JSON.parse(obj); 
 var arr_p = JSON.parse(arr); 
  
 var msg = "iframe function execute success\n\n"; 
 msg += "name:" + name + "\n"; 
 msg += "gender:" + obj_p.gender + "\n"; 
 msg += "age:" + obj_p.age + "\n"; 
 msg += "blog:" + arr_p[0] + "\n"; 
 msg += "weibo:" + arr_p[1] + "\n"; 
 
 alert(msg); 
 
 } 
 
 // exec main function 
 function exec_main(){ 
 // same domain 
 //FrameMessage.exec('', '', 'fMain', ['programmer', '{"first":"PHP","second":"javascript"}', '["EEG","NMG"]']); 
 
 // cross domain 
 FrameMessage.exec('http://localhost/execA.php', '', 'fMain', ['programmer', '{"first":"PHP","second":"javascript"}', '["EEG","NMG"]']); 
 } 
 </script> 
 
 </head> 
 
 <body> 
 <p>B.html iframe</p> 
 <p><input type="button" value="exec main function" onclick="exec_main()"></p> 
 </body> 
</html>

execA.php 与 execB.php

<?php 
require 'FrameMessage.class.php'; 
 
$frame = isset($_GET['frame'])? $_GET['frame'] : ''; 
$func = isset($_GET['func'])? $_GET['func'] : ''; 
$args = isset($_GET['args'])? $_GET['args'] : ''; 
 
$result = FrameMessage::execute($frame, $func, $args); 
 
echo $result; 
?>
Javascript 相关文章推荐
onkeypress字符按键兼容所有浏览器使用介绍
Apr 24 Javascript
通用javascript代码判断版本号是否在版本范围之间
Nov 29 Javascript
JS实现的多张图片轮流播放幻灯片效果
Jul 22 Javascript
vue.js绑定class和style样式(6)
Dec 09 Javascript
获取今天,昨天,本周,上周,本月,上月时间(实例分享)
Jan 04 Javascript
详解用webpack2.0构建vue2.0超详细精简版
Apr 05 Javascript
React降级配置及Ant Design配置详解
Dec 27 Javascript
vue计算属性computed的使用方法示例
Mar 13 Javascript
Vue实现拖放排序功能的实例代码
Jul 08 Javascript
微信小程序后台持续定位功能使用详解
Aug 23 Javascript
Vue 刷新当前路由的实现代码
Sep 26 Javascript
Vue插件之滑动验证码用法详解
Apr 05 Javascript
JQuery日期插件datepicker的使用方法
Mar 03 #Javascript
jQuery日历插件datepicker用法详解
Mar 03 #Javascript
初步使用Node连接Mysql数据库
Mar 03 #Javascript
初步使用bootstrap快速创建页面
Mar 03 #Javascript
JS动态增删表格行的方法
Mar 03 #Javascript
微信jssdk在iframe页面失效问题的解决措施
Mar 03 #Javascript
基于javascript html5实现多文件上传
Mar 03 #Javascript
You might like
让PHP支持页面回退的两种方法
2008/01/10 PHP
php xml实例 留言本
2009/03/20 PHP
仿Aspnetpager的一个PHP分页类代码 附源码下载
2012/10/08 PHP
php 判断字符串中是否包含html标签
2014/02/17 PHP
PHP5.3新特性小结
2016/02/14 PHP
php读取torrent种子文件内容的方法(测试可用)
2016/05/03 PHP
php读取qqwry.dat ip地址定位文件的类实例代码
2016/11/15 PHP
PHP 中TP5 Request 请求对象的实例详解
2017/07/31 PHP
针对thinkPHP5框架存储过程bug重写的存储过程扩展类完整实例
2018/06/16 PHP
如何在父窗口中得知window.open()出的子窗口关闭事件
2013/10/15 Javascript
实现非常简单的js双向数据绑定
2015/11/06 Javascript
学习掌握JavaScript中this的使用技巧
2016/08/29 Javascript
JS如何判断浏览器类型和详细区分IE各版本浏览器
2017/03/04 Javascript
AngularJS之自定义服务详解(factory、service、provider)
2017/04/14 Javascript
基于jQuery封装的分页组件
2017/06/26 jQuery
jQuery实现html双向绑定功能示例
2017/10/09 jQuery
EasyUI实现下拉框多选功能
2017/11/07 Javascript
Angular ElementRef简介及其使用
2018/10/01 Javascript
npm scripts 使用指南详解
2018/10/08 Javascript
vue router 源码概览案例分析
2018/10/09 Javascript
vue iview的菜单组件Mune 点击不高亮的解决方案
2019/11/01 Javascript
解决vue-photo-preview 异步图片放大失效的问题
2020/07/29 Javascript
解决vue单页面多个组件嵌套监听浏览器窗口变化问题
2020/07/30 Javascript
[52:44]VGJ.T vs infamous Supermajor小组赛D组败者组第一轮 BO3 第一场 6.3
2018/06/04 DOTA
Django项目中model的数据处理以及页面交互方法
2018/05/30 Python
tensorflow实现测试时读取任意指定的check point的网络参数
2020/01/21 Python
Django用数据库表反向生成models类知识点详解
2020/03/25 Python
在Matplotlib图中插入LaTex公式实例
2020/04/17 Python
Pycharm-community-2020.2.3 社区版安装教程图文详解
2020/12/08 Python
工业设计专业推荐信
2013/10/29 职场文书
同学会主持词
2014/03/18 职场文书
《草原的早晨》教学反思
2014/04/08 职场文书
计算机软件专业求职信
2014/06/10 职场文书
火锅店的活动方案
2014/08/15 职场文书
校园开放日新闻稿
2015/07/17 职场文书
婚礼必备主持词范本!
2019/07/23 职场文书