js中各种跨域问题实战小结(二)
这里接上篇:js中各种跨域问题实战小结(一)
后面继续学习的过程中,对上面第一篇有稍作休整。下面继续第二部分:
-->5.利用iframe和location.hash
-->6.window.name跨域实现
利用iframe和location.hash实现跨域
想必有很多人像我之前一样,或许只知道上面文中所说的那几种方法。所以,我刚了解到可以用iframe和location.hash来实现跨域的时候,我会想,为什么他们可以实现。iframe是什么,有什么特性,location.hash是什么又有什么特性。
准备:
>>1.MDN上说的<iframe>:HTML 的<iframe>(HTML inline框架元素)是一个嵌套的浏览上下文,他可以有效地嵌入另一个HTML页面到当前页面。在HTML 4.01中,一个文件可能包含一个头和一个身体或头部和一个框架集,而不是一个身体和一个框架集。然而,一个< iframe >可以被应用在正常的文件体。每个浏览上下文有它自己的会话历史和活动文档。浏览上下文包含嵌入的内容叫做父浏览上下文。顶级的浏览上下文(没有父)是典型的浏览器窗口。
了解到了<iframe>,我觉得另外两个相似的标签<frame>和<frameset>可以一起拿过来看下啦,这有篇文章放在一起总结了下:Frameset,Frame和Iframe
>>2.window.location:打开chrome的console,一起来试一下,很快就懂啦。我们从最基本的开始:
2.1 可以跳转到另一个页面:打开百度搜索的主页,然后在console中输入下面代码:
window.location = "http://www.cnblogs.com/skylar/";
看,是不是跳转到我的博客主页啦。
2.2 强制从服务器重新加载页面:既然来到了我的博客主页,就先别走,继续输入下面代码:
window.location.reload(true);
可以看到页面被重新加载了。
2.3 然后可以点击进去比如js中各种跨域问题实战小结(一)这篇文章,console输入:
location.hash = '#comments';
看看页面是不是跳到了最下面评论的位置。
其实还有两个特性:比如说alert当前url属性,通过修改window.location.search属性向服务器发送一个字符串,这你可以移步这里自行脑补:MDN window.location 。
这里有用的是下面这个例子:location.hash理解demo
这里可以查看代码:https://github.com/zhangmengxue,因为我们就是要利用location.hash的特性来加上iframe来实现跨域,看完了这个demo,我们就可以开始实现跨域了。(请用chrome打开,还有些需要总结的兼容性问题)
实现:
我为了模拟两个不同的域,在SAE上面创建了两个wordpress应用,如果你之前也不懂SAE是什么的话,这个小简介:新浪SAE 会让你大致了解到SAE是做什么的,如何开始使用它。我的两个应用:
看到url了吧,是不同域喔,环境模拟好了,我可以开始尝试跨域了。
在[http://1.daeskylar.sinaapp.com/]下有两个文件 a.html和c.html;
在[http://1.skylarisdae.sinaapp.com/]下有文件 b.html
我想要在a.html中访问我在b.html中模拟的数据Helloworld!
好呀,那现在点击 有a.html和c.html的这个域 访问我在这个域上的a.html文件,它应该会告诉你他是a.html页面,然后他会访问到了我放在b.html中的HelloWorld!
跨域这样就实现了喔,那具体是怎样实现的呢?
原理:
a.html想和b.html通信(在a.html中动态创建一个b.html的iframe来发送请求);
但是由于“同源策略”的限制他们无法进行交流(b.html无法返回数据),于是就找个中间人:与a.html同域的c.html;
b.html将数据传给c.html(b.html中创建c.html的iframe),由于c.html和a.html同源,于是可通过c.html将返回的数据传回给a.html,从而达到跨域的效果。
三个页面之间传递参数用的是location.hash,改变hash并不会导致页面刷新(这点很重要)。
------------------------------------------------------------------------------------------------------------------------------------------------
a.html---①--->b.html----②--->c.html---③--->a.html——>a.html便获得到了b.html中的数据
①通过iframe的location.hash传参数给b.html ;
②通过iframe的location.hash传参数给c.html ;
③同域传给a.html。
-------------------------------------------------------------------------------------------------------------------------------------------------
代码:
a.html:
<!doctype html>
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<title>localhost:a.html</title> <style type="text/css"> </style>
</head> <body>
<script type="text/javascript">
alert('我是a页面');
function sendRequest(){
//动态创建个iframe
var ifr = document.createElement('iframe');
ifr.style.display = 'none';
//跨域发送请求给b.html,参数是#sayHello
ifr.src = 'http://1.skylarisdae.sinaapp.com/b.html#sayHello';
document.body.appendChild(ifr);
}
function checkHash(){
var data = location.hash?location.hash.substring(1):'';
if(data){
//这里处理返回值
alert(data);
location.hash = '';
}
}
setInterval(checkHash,1000);
window.onload = sendRequest;
</script>
</body>
</html>
c.html:
<!doctype html>
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<title>localhost:c.html</title> <style type="text/css"> </style>
</head> <body>
<script type="text/javascript">
//因为c.html和a.html属于同一个域,所以可以通过改变其location.hash的值,可以通过parent.parent获取a.html的window对象
parent.parent.location.hash = self.location.hash.substring(1);
</script>
</body>
</html>
b.html:
<!doctype html>
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<title>另某个域的:b.html</title> <style type="text/css"> </style>
</head> <body>
<script type="text/javascript">
function checkHash(){
var data = '';
//模拟一个简单的参数处理操作
switch(location.hash){
case '#sayHello':
data = 'HelloWorld';
break;
case '#sayHi':
data = 'HiWorld';
break;
default : break;
}
data && callBack('#'+data);
}
function callBack(hash){
var proxy = document.createElement('iframe');
proxy.style.display = 'none';
proxy.src = 'http://1.daeskylar.sinaapp.com/c.html'+hash;
document.body.appendChild(proxy);
}
window.onload = checkHash;
</script>
</body>
</html>
这里参考了:javascript跨域详解
利用window.name实现跨域
实现:
我还是利用上面我在sae上面创建的应用:
在[http://1.daeskylar.sinaapp.com/]下有两个文件 wantdata.html和proxy.html;
在[http://1.skylarisdae.sinaapp.com/]下有文件 data.html。
我想要在wantdata.html中访问到我在data.html中存在window.name中的数据,是个字符串,就叫‘我拿到数据啦!’。
访问这里:http://1.daeskylar.sinaapp.com/wantdata.html 应该可以看到alert出的数据喔。
原理:
MDN上的window.name是这样说的:
窗口的名称,主要用于设置超链接和表格对象。Windows不需要有名字。
它也被用于提供跨域通信的一些框架(例如,sessionvars和Dojo的DojoX。IO。windowname)为JSONP更安全的替代方案。
window.name 的美妙之处在于:name 值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。
这篇文章讲解的非常详细,很值得阅读:使用window.name解决跨域问题
实现起来基本步骤如下:
1.创建一个iframe,把其src指向目标页面(提供web service的页面,该目标页面会把数据附加到这个iframe的window.name上,大小一般为2M,IE和firefox下可以大至32M左右;数据格式可以自定义,如json字符串);
2.监听iframe的onload事件,在此事件中立即设置这个iframe的src指向本地域的某个页面,由本地域的这个页面读取iframe的window.name。
3.获取数据以后销毁这个iframe,释放内存;这也保证了安全(不被其他域frame js访问)。
总结起来即:iframe的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。
代码:
wantdata.html
<!doctype html>
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<title>window.name跨域demo</title> <style type="text/css"> </style>
</head> <body>
<script type="text/javascript">
var state = 0,
iframe = document.createElement('iframe'),
loadfn = function() {
if (state === 1) {
var data = iframe.contentWindow.name; // 读取数据
alert(data); //弹出'拿到数据啦!'
//下面立即销毁iframe,释放内存,也保证安全
iframe.contentWindow.document.write('');
iframe.contentWindow.close();
document.body.removeChild(iframe);
} else if (state === 0) {
state = 1;
iframe.contentWindow.location = "http://1.daeskylar.sinaapp.com/proxy.html"; // 设置的代理文件
}
};
iframe.src = 'http://1.skylarisdae.sinaapp.com/data.html';
if (iframe.attachEvent) {
iframe.attachEvent('onload', loadfn);
} else {
iframe.onload = loadfn;
}
document.body.appendChild(iframe);
</script>
</body>
</html>
data.html
<!doctype html>
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<title>data页</title> <style type="text/css"> </style>
</head> <body>
<script type="text/javascript">
window.name = '拿到跨域的数据啦!'; // 这里是要传输的数据,大小一般为2M,IE和firefox下可以大至32M左右
// 数据格式可以自定义,如json、字符串
</script>
</body>
</html>
proxy.html
<!doctype html>
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<title>window.name跨域demo</title> <style type="text/css"> </style>
</head> <body>
<span>这里是代理空文件</span>
<script type="text/javascript"> </script>
</body>
</html>
这里参考了:window.name实现跨域数据传输 使用window.name解决跨域问题
从一大早写到现在了,午觉也没睡,写不动了,后面再来个三吧,补上:
-->7.HTML5 postMessage实现跨域
js中各种跨域问题实战小结(二)的更多相关文章
- js中各种跨域问题实战小结(一)
什么是跨域?为什么要实现跨域呢? 这是因为JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象.也就是说只能访问同一个域中的资源.我觉得这就有必要了解下javascript中的同源策略 ...
- js中各种跨域问题实战小结
什么是跨域?为什么要实现跨域呢? 这是因为JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象.也就是说只能访问同一个域中的资源.我觉得这就有必要了解下javascript中的同源 ...
- JS中实现跨域的方法总结
今天早上在地铁看了点基础知识的考察题,看到了一个JS跨域的问题,仔细想了想自己脑子里竟然只剩下jsonp跨域和用nginx反向代理进行跨域,想着还有别的几种方法,就是想不起来,这个人呢,一上岁数这个脑 ...
- 001_Three.js中的跨域问题
001_Three.js中的跨域问题 [情景描述]: 在初始化模型,引入字体和纹理皮肤图片的时候,由于跨域问题,出现了以下提示: Access to image at 'file:///F:/User ...
- JS中的跨域问题
一.什么是跨域? 1.定义:跨域是指从一个域名的网页去请求另一个域名的资源.比如从www.baidu.com 页面去请求 www.google.com 的资源.但是一般情况下不能这么做,它是由浏览器的 ...
- js中的跨域方法总结
什么是跨域? 浏览器的安全策略,只要协议,域名,端口有任何一个不同,就被当做不同的域. 下面对http://www.qichedaquan.com的同源检测 http://www.qichedaqua ...
- JS 中的跨域请求
跨域请求并不仅仅只是 Ajax 的跨域请求,而是对于一个页面来说,只要它请求了其他域名的资源了,那么这个过程就属于跨域请求了. 比如,一个带有其他域名的 src 的 <img> 标签,以及 ...
- js中的跨域
因为javascript的同源策略,导致它普通情况下不能跨域,直到现在,我还是不能完全理解js跨域的几种方法,没办法,只能慢慢学习,慢慢积累,这不,几天又在园里看到一篇博文,有所收获,贴上来看看; 原 ...
- 【原创】Vue.js 中 axios 跨域访问错误
1.假如访问的接口地址为 http://www.test.com/apis/index.php (php api 接口) 2.而开发地址为http://127.0.0.1:8080,当axios发起 ...
随机推荐
- 什么是publickeytoken及publickeytoken的作用
什么是publickeytoken及publickeytoken的作用 dll的publickeytoken的作用.
- MongoDB基本命令用
成功启动MongoDB后,再打开一个命令行窗口输入mongo,就可以进行数据库的一些操作. 输入help可以看到基本操作命令: show dbs:显示数据库列表 show collections:显 ...
- nio加强服务端并发
究了一下Android推送,方式很多,比如用框架或者用第三方服务,在此并不讨论个中优劣.抱着学习的态度,本人不太喜欢用一些现成的东西,所以自己动手实现了一套简单的推送机制.使用TCP长连接,完成服务器 ...
- jquery easyui window中的datagrid,只能显示一次问题
最近项目中用到easyui 的动态创建window ,window中嵌入了datagruid.第一次打开是能显示数据,但再次打开时确没显示: 注:url已成功返回了数据. 多次查阅easyui帮助文档 ...
- Linux下修改mysql密码
# /etc/init.d/mysql stop# mysqld_safe --user=mysql --skip-grant-tables --skip-networking &# mysq ...
- 移动web前端小结(一)--摘自小鹿_同学
一.框架 框架:Bootstrap+HTML5 Boilerplate. 两个框架整合到一起可以看一下这位大神的文章:<使用 Bootstrap 和 HTML5 Boilerplate 开始一个 ...
- 用Asp.net写自己的服务框架
阅读目录 开始 理解Asp.net管线 HttpHandler HttpModule 关于Content-Encoding的解释 选 HttpHandler 还是 HttpModule ? 看不见的性 ...
- luogu p2330[SCOI05] 繁忙的都市——瓶颈生成树
P2330 05四川 繁忙的都市 题目描述 城市C是一个非常繁忙的大都市,城市中的道路十分的拥挤,于是市长决定对其中的道路进行改造.城市C的道路是这样分布的:城市中有n个交叉路口,有些交叉路口之间有道 ...
- Windows下nginx+php配置
1. 首先,将 nginx.conf 中的 PHP 配置注释去掉. # pass the PHP scripts to FastCGI server listening on # #location ...
- Inno setup中定制安装路径
我的程序修改了安装界面,所以我的界面中提供了更改安装路径的方法. 用户修改后的路径会被传回inno setup脚本,脚本中需要做的事情如下: 1,写一个函数,来返回新的安装路径,如: function ...