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:

 1 <!doctype html>
 2 <html>
 3 <head>
 4 <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
 5 <title>localhost:a.html</title>
 6
 7 <style type="text/css">
 8
 9 </style>
10 </head>
11
12 <body>
13 <script type="text/javascript">
14     alert(‘我是a页面‘);
15 function sendRequest(){
16   //动态创建个iframe
17   var ifr = document.createElement(‘iframe‘);
18   ifr.style.display = ‘none‘;
19   //跨域发送请求给b.html,参数是#sayHello
20   ifr.src = ‘http://1.skylarisdae.sinaapp.com/b.html#sayHello‘;
21   document.body.appendChild(ifr);
22 }
23 function checkHash(){
24   var data = location.hash?location.hash.substring(1):‘‘;
25   if(data){
26     //这里处理返回值
27     alert(data);
28     location.hash = ‘‘;
29   }
30 }
31 setInterval(checkHash,1000);
32 window.onload = sendRequest;
33 </script>
34 </body>
35 </html>

c.html:

 1 <!doctype html>
 2 <html>
 3 <head>
 4 <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
 5 <title>localhost:c.html</title>
 6
 7 <style type="text/css">
 8
 9 </style>
10 </head>
11
12 <body>
13 <script type="text/javascript">
14 //因为c.html和a.html属于同一个域,所以可以通过改变其location.hash的值,可以通过parent.parent获取a.html的window对象
15 parent.parent.location.hash = self.location.hash.substring(1);
16 </script>
17 </body>
18 </html>

b.html:

 1 <!doctype html>
 2 <html>
 3 <head>
 4 <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
 5 <title>另某个域的:b.html</title>
 6
 7 <style type="text/css">
 8
 9 </style>
10 </head>
11
12 <body>
13 <script type="text/javascript">
14 function checkHash(){
15     var data = ‘‘;
16     //模拟一个简单的参数处理操作
17     switch(location.hash){
18         case ‘#sayHello‘:
19               data = ‘HelloWorld‘;
20               break;
21         case ‘#sayHi‘:
22               data = ‘HiWorld‘;
23               break;
24         default : break;
25     }
26     data && callBack(‘#‘+data);
27 }
28 function callBack(hash){
29    var proxy = document.createElement(‘iframe‘);
30    proxy.style.display = ‘none‘;
31    proxy.src = ‘http://1.daeskylar.sinaapp.com/c.html‘+hash;
32    document.body.appendChild(proxy);
33 }
34 window.onload = checkHash;
35 </script>
36 </body>
37 </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

 1 <!doctype html>
 2 <html>
 3 <head>
 4 <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
 5 <title>window.name跨域demo</title>
 6
 7 <style type="text/css">
 8
 9 </style>
10 </head>
11
12 <body>
13 <script type="text/javascript">
14     var state = 0,
15     iframe = document.createElement(‘iframe‘),
16     loadfn = function() {
17         if (state === 1) {
18             var data = iframe.contentWindow.name;    // 读取数据
19             alert(data);    //弹出‘拿到数据啦!‘
20             //下面立即销毁iframe,释放内存,也保证安全
21             iframe.contentWindow.document.write(‘‘);
22             iframe.contentWindow.close();
23             document.body.removeChild(iframe);
24         } else if (state === 0) {
25             state = 1;
26             iframe.contentWindow.location = "http://1.daeskylar.sinaapp.com/proxy.html";    // 设置的代理文件
27         }
28     };
29     iframe.src = ‘http://1.skylarisdae.sinaapp.com/data.html‘;
30     if (iframe.attachEvent) {
31         iframe.attachEvent(‘onload‘, loadfn);
32     } else {
33         iframe.onload  = loadfn;
34     }
35     document.body.appendChild(iframe);
36 </script>
37 </body>
38 </html>

data.html

 1 <!doctype html>
 2 <html>
 3 <head>
 4 <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
 5 <title>data页</title>
 6
 7 <style type="text/css">
 8
 9 </style>
10 </head>
11
12 <body>
13 <script type="text/javascript">
14     window.name = ‘拿到跨域的数据啦!‘;    // 这里是要传输的数据,大小一般为2M,IE和firefox下可以大至32M左右
15                                      // 数据格式可以自定义,如json、字符串
16 </script>
17 </body>
18 </html>

proxy.html

 1 <!doctype html>
 2 <html>
 3 <head>
 4 <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
 5 <title>window.name跨域demo</title>
 6
 7 <style type="text/css">
 8
 9 </style>
10 </head>
11
12 <body>
13     <span>这里是代理空文件</span>
14 <script type="text/javascript">
15
16 </script>
17 </body>
18 </html>

这里参考了:window.name实现跨域数据传输   使用window.name解决跨域问题

从一大早写到现在了,午觉也没睡,写不动了,后面再来个三吧,补上:

-->7.HTML5 postMessage实现跨域

时间: 2024-08-08 17:46:43

js中各种跨域问题实战小结(二)的相关文章

js中各种跨域问题实战小结

什么是跨域?为什么要实现跨域呢? 这是因为JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象.也就是说只能访问同一个域中的资源.我觉得这就有必要了解下javascript中的同源策略是怎么回事了:javascript的同源策略 于是当我们想某些特定的功能的时候,实现合理的跨域请求就显得比较重要了. -->1.原生Ajax对象xhr的跨域 -->2.简单jsonp -->3.图像Ping -->4.document.domain+iframe实现跨域 javascr

JS 中的跨域请求

跨域请求并不仅仅只是 Ajax 的跨域请求,而是对于一个页面来说,只要它请求了其他域名的资源了,那么这个过程就属于跨域请求了. 比如,一个带有其他域名的 src 的 <img> 标签,以及页面中引入的其他第三方的 CSS 样式等. 对于 img 以及 CSS 而言,跨域请求本身并没有更多的安全问题,因为这些请求都属于只读请求,并不会对源资源造成副作用. 而如果跨域请求是从脚本里面发出去的,由于脚本具有高度灵活性,浏览器出于安全考虑,会根据同源策略来限制它的功能,使得正常情况下,脚本只能请求同源

JS中的跨域问题

跨域访问出错信息:No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9100' is therefore not allowed access. The response had HTTP status code 400. 1.跨域的概念 跨域是指从一个域名的网页去请求另一个域名的资源.比如从www.baidu.com 页面去请求 www.g

php中ajax跨域请求---小记

php中ajax跨域请求---小记 前端时间,遇到的一个问题,情况大约是这样: 原来的写法: 前端js文件中: $.ajax({ type:'get', url:'http://wan.xxx.com/xxx.js', success:function(data){ ......... } }) 很简单的一个ajax请求:后面在做迁移的时候,由于系统目录的安排,js文件放到了,img.xxx.com域名下,这样就设计到了跨域问题,于是就改成了这样: $.ajax({ type:'get', ur

vue.js学习之 跨域请求代理与axios传参

vue.js学习之 跨域请求代理与axios传参 一:跨域请求代理 1:打开config/index.js module.exports{ dev: { } } 在这里面找到proxyTable{},改为这样: proxyTable: { '/api': { target: 'http://121.41.130.58:9090',//设置你调用的接口域名和端口号 别忘了加http changeOrigin: true, pathRewrite: { '^/api': ''//这里理解成用'/ap

ASP.NET MVC中设置跨域

ASP.NET MVC中设置跨域 1.什么是跨域请求 js禁止向不是当前域名的网站发起一次ajax请求,即使成功respone了数据,但是你的js仍然会报错.这是JS的同源策略限制,JS控制的并不是我们网站编程出现了问题.客户端(网页)和后台编程都可以有效解决这个问题.客户端可以通过JSONP来完成跨域访问:在ES6中为了解除同源策略问题,想出一个办法:当被请求网站为响应头respone添加了一个名为Access-Control-Allow-Origin的header,设置其值等于发起请求网站的

跨域问题实战 2

跨域问题实战 2 背景 由于整个项目提供出去的API都不是跨域的只是个别是需要跨域的,所以再上一次跨域问题实战中,自己是直接再controller层其中需要提供出去跨域的方法里设置了HttpServletResponse.setHeader("Access-Control-Allow-Origin","*").而且上次提供出去的只是一次简单的get请求,而不是复杂请求.但是呢,这次的需求是记录用户行为日志的一次跨域请求,也就是说是一次post请求.其中就涉及到htt

【JS】AJAX跨域-被调用方与调用方解决方案(二)

解决跨域问题 跨域问题说明,参考[JS]AJAX跨域-JSONP解决方案(一) 实例,使用上一章([JS]AJAX跨域-JSONP解决方案(一))的实例 解决方案三(被调用方支持跨域) 被调用方解决,基于支持跨域的解决思路,基于Http协议关于跨域的相关规定,在响应头里增加指定的字段告诉浏览器,允许调用 跨域请求是直接从浏览器发送到被调用方,被调用方在响应头里增加相关信息,返回到页面,页面能正常获取请求内容. 1.服务端增加一个过滤器(CrossFilter.java),过滤所有请求,在请求响应

ASP.NET中Cookie跨域的问题及解决代码

ASP.NET中Cookie跨域的问题及解决代码 http://www.liyumei.net.cn/post/share18.html Cookies揭秘  http://www.cnblogs.com/zhangziqiu/archive/2009/08/06/cookies-javascript-aspnet.html 最近在项目开发中遇到一个很棘手的问题,一个用户在顶级域名登录后,跳转到自己所拥有的二级域名下管理二级网站时,cookie丢失了,一直找解决办法找了整整两天,百度谷歌一大堆,