利用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 <metahttp-equiv="Content-Type"content="text/html; charset=UTF-8"> 5 <title>该页面的路径是:http://a.com/request.html</title> 6 </head> 7 <body> 8 <pid="result">这里将会填上响应的结果</p> 9 <aid="sendBtn"href="javascript:void(0)">点击,发送跨域请求</a> 10 <iframeid="serverIf"></iframe> 11 <scripttype="text/javascript"> 12 document.getElementById("sendBtn").onclick= function() {13 varurl= "http://b.com/response.html";14 varfn= "GetPerson";//这是定义在response.html的方法15 varreqdata= '{"id" : 24}';//这是请求的参数16 varcallback= "CallBack";//这是请求全过程完成后执行的回调函数,执行最后的动作17 CrossRequest(url, fn, reqdata, callback);//发送请求18 }19 functionCrossRequest(url, fn, reqdata, callback) {20 varserver=document.getElementById("serverIf");21 server.src=url+ "?fn=" +encodeURIComponent(fn)+ "&data=" +encodeURIComponent(reqdata)+ "&callback=" +encodeURIComponent(callback);//这里由request.html向response.html发送的请求其实就是通过iframe的src将参数与回调方法传给response.html22 }23 functionCallBack(data) {//回调函数24 varstr= "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 <metahttp-equiv="Content-Type"content="text/html; charset=UTF-8"> 5 <title>该页面的路径是:http://b.com/response.html</title> 6 </head> 7 <body> 8 <iframeid="proxy"></iframe> 9 <scripttype="text/javascript"> 10 function_request(reqdata, url, callback) {//通用方法,ajax请求11 varxmlhttp;12 if(window.XMLHttpRequest) {13 xmlhttp= newXMLHttpRequest();14 }15 else{16 xmlhttp= newActiveXObject("Microsoft.XMLHTTP");17 }18 xmlhttp.onreadystatechange= function() {19 if(xmlhttp.readyState== 4 &&xmlhttp.status== 200) {20 vardata=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 varquery=location.href.split("?")[1];30 varvalue=decodeURIComponent(query.split(key+ "=")[1].split("&")[0]);31 returnvalue;32 }33 functionGetPerson(reqdata, callback) {//向process.php发送ajax请求34 varurl= "process.php";35 varfn= function(data) {36 varproxy=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 varfn=_getQuery("fn");43 varreqdata=_getQuery("data");44 varcallback=_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 <?php2 $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 <metahttp-equiv="Content-Type"content="text/html; charset=UTF-8"> 5 <title>该页面的路径是:http://a.com/proxy.html</title> 6 </head> 7 <body> 8 <scripttype="text/javascript"> 9 function_getUrl(key) {//通用方法,获取URL参数10 varquery=location.href.split("?")[1];11 varvalue=decodeURIComponent(query.split(key+ "=")[1].split("&")[0]);12 returnvalue;13 }14 (function() {15 varcallback=_getUrl("callback");16 vardata=_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,最后还是奉上那句老话:所拥有的技术并不是最重要的,最重要的是学习的能力。
转载于:https://www.cnblogs.com/xueming/archive/2013/02/01/CrossDomainAjax.html
利用iframe实现ajax 跨域通信的解决方案相关推荐
- ajax跨域原理以及解决方案
ajax跨域原理以及解决方案 参考文章: (1)ajax跨域原理以及解决方案 (2)https://www.cnblogs.com/bojuetech/p/5895767.html (3)https: ...
- JQuery的Ajax跨域请求的解决方案
JQuery的Ajax跨域请求的解决方案 参考文章: (1)JQuery的Ajax跨域请求的解决方案 (2)https://www.cnblogs.com/amylis_chen/p/4703735. ...
- Ajax跨域请求与解决方案
同域与跨域请求 同域请求: 网络协议, 域名,端口号都一致,则为同域(同源)请求 http://www.sina.com.cn:8090/index.html 跨域请求: 浏览器对于javascrip ...
- AJAX跨域问题及解决方案
文章目录 跨域 哪些方式可以进行跨域 部署服务器 部署模块 ajax1 ajax2 测试 跨域解决方案 方案1:设置响应头 方案2:jsonp 深入一下jsonp 方案3:代理机制(httpclien ...
- jQuery利用JSONP解决AJAX跨域请求
出于安全方面的考虑,页面中的JavaScript无法访问其他服务器上的数据,即"同源策略".而跨域就是通过某些手段来绕过同源策略限制,实现不同服务器之间通信的效果. JSON(Ja ...
- 利用JSONP解决AJAX跨域问题的原理与jQuery解决方案
写在前面 跨域的解决方案有多种,其中最常见的是使用同一服务器下的代理来获取远端数据,再通过ajax进行读取,而在这期间经过了两次请求过程,使得获取数据的效率大大降低,这篇文章蓝飞就为大家介绍一下解决跨 ...
- 菜鸟教程 php跨域,PHP Ajax 跨域问题最佳解决方案
本文通过设置Access-Control-Allow-Origin来实现跨域. 例如:客户端的域名是client.runoob.com,而请求的域名是server.runoob.com. 如果直接使用 ...
- PHP Ajax 跨域问题最佳解决方案
本文通过设置Access-Control-Allow-Origin来实现跨域. 例如:客户端的域名是client.runoob.com,而请求的域名是server.runoob.com. 如果直接使用 ...
- PHP ajax跨域问题最佳解决方案
一.本文通过设置Access-Control-Allow-Origin来实现跨域. 例如:客户端的域名是client.runoob.com,而请求的域名是server.runoob.com. 如果直接 ...
最新文章
- ubuntu 16.04 ROS + kinect v2 安装
- 苹果连接电脑只能充电_苹果 iPhone 12 曝充电 Bug:多口充电器无一幸免 只能用单独充电头 - 手机 - IT商业网...
- SpringBoot之旅第一篇-初探
- PHP标量类型中整型类型的,PHP数据类型概述
- phpmyadmin忘记mysql密码_忘记phpmyadmin登录密码怎么办
- 使用 core dump 查找程序遇到严重问题退出的原因
- sql能查到数据 dataset对象里面没有值_新零售数据分析报告
- Element表格嵌入复选框以及单选框
- 用delphi操作excel
- CKEditor设置背景图片及宽高
- pb 修改数据窗口种指定字段位置_如何在PB数据窗口中修改数据设置数据窗口的更新属性...
- 《第一行代码》第三版之我的第一行Android代码(一)
- swift 网络----利用URLSession的Data Task下载单张图片(包含图片的增量下载)
- (Research)泛癌单细胞分析揭示肿瘤微环境中癌相关成纤维细胞的异质性和可塑性
- “吃鸡”吗?《和平精英》来了,感觉不一般
- 一文了解AAAI国际会议–附: 各年论文连接
- php定义一个矩形类rectangle,Python3面向对象—点和矩形类
- 微弱电流检测放大器PCB布线布局设计
- quartus 2 低版本打开IP核设置窗口的方法
- 产品故事:一家服装厂的创新之路
热门文章
- python游戏编程快速上手第四版dragon_《Python游戏编程快速上手》——导读
- python中模块和函数_Python中函数和模块的体验与使用
- ubuntu安装ffmpeg_安装 Jellyfin 开始肥宅生活
- 面试mysql中怎么创建索引_阿里面试:MySQL如何设计索引更高效?
- MySQL乱码问题解决步骤详解
- 使用rsync同步网路备份
- Linux性能监测工具Nmon介绍及其使用
- Auth模块、Forms组件
- 脚本其实很简单-windows配置核查程序(1)
- httpd: apr_sockaddr_info_get() failed for bogon