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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
<!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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
<!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。如下图
点击B.html 的 exec main function button,执行成功,弹出 main function execute success。如下图
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调用
1
2
3
|
<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 调用
1
2
3
|
<script type=
"text/javascript"
>
parent.parent.fMain();
// execute main function
</script>
|
这样就能实现 A.html 与 B.html 跨域相互调用。
A.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
<!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.style.display =
'none'
;
document.body.appendChild(exec_obj);
}
else
{
}
}
</script>
</head>
<body>
<p>A.html main</p>
<p><input type=
"button"
value=
"exec iframe function"
onclick=
"exec_iframe()"
></p>
</body>
</html>
|
B.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<!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.style.display =
'none'
;
document.body.appendChild(exec_obj);
}
else
{
}
}
</script>
</head>
<body>
<p>B.html iframe</p>
<p><input type=
"button"
value=
"exec main function"
onclick=
"exec_main()"
></p>
</body>
</html>
|
execA.html
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<!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
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<!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>
|
执行如下图:
php main 与 iframe 相互通讯类(同域/跨域)
把main与iframe相互通讯的方法封装成类,主要有两个文件,
JS:FrameMessage.js 实现调用方法的接口,如跨域则创建临时iframe,调用同域执行者。
PHP:FrameMessage.class.php 实现接收到跨域请求时,根据参数返回执行方法的JS code。
功能如下:
1.支持同域与跨域通讯
2.传递的方法参数支持字符串,JSON,数组等。
FrameMessage.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
/** 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
<?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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
<!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 -->
</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
1
2
3
4
5
6
7
8
9
10
11
|
<?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
;
?>
|