这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据。只要协议、域名、端口有任何一个不同,都被当作是不同的域。

特别注意两点:

#1、如果是协议和端口造成的跨域问题“前台”是无能为力的;
#2、在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。

要解决跨域的问题,我们可以使用以下几种方法:

方法一、通过jsonp跨域

JSONP包含两部分:回调函数和数据。 
回调函数:当响应到来时要放在当前页面被调用的函数。 
数据:就是传入回调函数中的json数据,也就是回调函数的参数了。

/*handleResonse({"data": "zhe"})*/
//原理如下://当我们通过script标签请求时//后台就会根据相应的参数(json,handleResponse)//来生成相应的json数据(handleResponse({"data": "zhe"}))//最后这个返回的json数据(代码)就会被放在当前js文件中被执行//至此跨域通信完成//1、使用JS动态生成script标签,进行跨域操作
functionhandleResponse(response){console.log('The responsed data is: '+response.data);//处理获得的Json数据
}var script = document.createElement('script');
script.src= 'http://www.example.com/data/?callback=handleResponse';
document.body.insertBefore(script, document.body.firstChild);--------------------------
//2、手动生成script标签
functionhandleResponse(response){console.log('The responsed data is: '+response.data);//处理获得的Json数据
}<script src="http://www.example.com/data/?callback=handleResponse"></script>
--------------------------
//3、使用jQuery进行jsonp操作//jquery会自动生成一个全局函数来替换callback=?中的问号,之后获取到数据后又会自动销毁//$.getJSON方法会自动判断是否跨域,不跨域的话,就调用普通的ajax方法;跨域的话,则会以异步加载js文件的形式来调用jsonp的回调函数。
<script>$.getJson('http://www.example.com/data/?callback=?',function(jsondata){//处理获得的Json数据
});</script>

jsonp虽然很简单,但是有如下缺点:

#1)安全问题(请求代码中可能存在安全隐患)#2)要确定jsonp请求是否失败并不容易

方法二、通过document.domain+iframe来跨子域(只有在主域相同的时候才能使用该方法)

浏览器同源策略限制:

#(1)不能通过ajax的方法去请求不同源中的文档。
#(2)浏览器中不同域的框架之间是不能进行js的交互操作的。

所以,在不同的框架之间(父子或同辈),是能够获取到彼此的window对象的,但不能使用获取到的window对象的属性和方法(html5中的postMessage方法是一个例外),总之,你可以当做是只能获取到一个几乎无用的window对象。
  例如,在一个页面 http:// www.example.com/a.html 中,有一个iframe框架它的src是http:// example.com/b.html, 很显然,这个页面与它里面的iframe框架是不同域的,所以我们是无法通过在页面中书写js代码来获取iframe中的东西的:

1 //http://www.example.com/a.html 页面中
2 <script>
3 functiononLoad(){4     var iframe = document.getElementById('iframe');5     var win =iframe.contentWindow;6     //这里能够获取到iframe中的window对象,但是window对象的属性和方法几乎不可用。
7     var doc = win.document;//这里获取不到iframe中的document对象
8     var name = win.name;//这里获取不到window对象的name属性
9 ······10 }11 <iframe id = "iframe" src ="http:// example.com/b.html" onload = "onLoad()"></iframe> 

所以我们就要用到document.domain

1) 在页面http:// www.a.com/dir/a.html中设置document.domain:

1 <iframe src = "http://script.a.com/dir/b.html" id="iframe" onload = "loLoad()"></iframe>
2 <script>
3 document.domain = "a.com";//设置成主域
4 functiontest(){5     var iframe = document.getElementById("iframe");6     var win =iframe.contentWindow;7     //在这里就可以操作b.html
8 }9 </script>

2) 在http:// script.a.com/dir/b.html也需要显示的设置document.domain

1 <script>
2     document.domain = "a.com";3 </script>

注意,document.domain的设置是有限制的:

  我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同。
  例如:a.b.c.com 中某个文档的document.domain 可以设成a.b.c.com、b.c.com 、c.com中的任意一个

方法三、使用window.name+iframe来进行跨域

window的name属性特征:name 值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB),即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面window.name都有读写的权限。

  正是由于window的name属性的特征,所以可以使用window.name来进行跨域。
  举例:
  1)在一个a.html页面中,有如下代码:

1 <script>
2     window.name = "哈哈,我是页面a设置的值哟!";3     //设置window.name的值
4     setTimeout(function(){5         window.location = 'b.html';6     },3000);//3秒后把一个新页面载入当前window
7 </script>

2)再在b.html中读取window.name的值:

1 <script>
2     alert(window.name);//读取window.name的值
3 </script>

3)a.html载入3秒后,跳转到b.html页面中,结果为

#注意:
#1.window.name的值只能是字符串的形式,这个字符串的大小最大能允许2M左右甚至更大的一个容量,具体取决于不同的浏览器。

接下来使用window.name进行跨域举例

  比如:有一个example.com/a.html页面,需要通过a.html页面里的js来获取另一个位于不同域上的页面cnblogs.com/data.html里的数据。
  1)创建cnblogs.com/data.html代码:

1 <script>
2     window.name = "我是data.html的数据,所有可以转化为字符串来传递的数据都可以在这里使用,比如这里可以传递Json数据";3 </script>

2)创建example.com/a.html的代码:
  想要即使a.html页面不跳转也能得到data.html里的数据。在a.html页面中使用一个隐藏的iframe来充当一个中间人角色,由iframe去获取data.html的数据,然后a.html再去得到iframe获取到的数据。

1 <script>
2     functiongetData(){3     //iframe载入data.html页面会执行此函数
4         var ifr = document.getElementById("iframe");5         ifr.onload = function(){6         //这个时候iframe和a.html已经处于同一源,可以互相访问
7             var data =ifr.contentWindow.name;8 //获取iframe中的window.name,也就是data.html中给它设置的数据
9 alert(data);10 }11         ifr.src = 'b.html';//这里的b.html为随便一个页面,只要与a.html同源就行,目的是让a.html能够访问到iframe中的东西,否则访问不到
12 }13 </script>
14 <iframe id = "iframe" src = "cnblogs.com/data.html" style = "display:none" onload = "getData()"></iframe>

方法四、使用window.postMessage方法来跨域(不常用)

 window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源(可实现跨域),目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。
  message:为要发送的消息,类型只能为字符串;
  targetOrigin:用来限定接收消息的那个window对象所在的域,如果不想限定域,可以使用通配符 “*”。

1)创建www.test.com/a.html页面代码:

1 <script>
2 functiononLoad(){3     var iframe = document.getElementById("iframe");4     var win =iframe.contentWindow;5     win.postMessage('哈哈,我是来自页面a.html的信息哟!','*');//向不同域的www.script.com/b.html发送消息
6 }7 </script>
8 <iframe id="iframe" src="www.script.com/b.html" οnlοad="onLoad()"></iframe>

2)创建www.script.com/b.html页面代码:

1 <script>
2 window.onmessage = function(e){//注册message时间来接收消息
3     e = e || event;            //获取时间对象
4     alert(e.data);             //通过data属性来得到传送的消息
5 }6 </script>

优点:使用postMessage来跨域传送数据还是比较直观和方便的; 
缺点: IE6、IE7不支持,所以用不用还得根据实际需要来决定。

方法五、使用跨域资源共享(CORS)来跨域

CORS:一种跨域访问的机制,可以让AJAX实现跨域访问;CORS允许一个域上的网络应用向另一个域提交跨域AJAX请求。
服务器设置Access-Control-Allow-Origin HTTP响应头之后,浏览器将会允许跨域请求.
就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。

1) IE中对CORS的实现是通过xdr

1 var xdr = newXDomainRequest();2 xdr.onload = function(){3 console.log(xdr.responseText);4 }5 xdr.open('get', 'http://www.test.com');6 ......7 xdr.send(null);

2) 其它浏览器中的实现就在xhr中

1 var xhr =  newXMLHttpRequest();2 xhr.onreadystatechange = function() {3   if(xhr.readyState === 4 && xhr.status === 200){4 console.log(xhr.responseText);5 }6 }7 }8 xhr.open('get', 'http://www.test.com');9 ......10 xhr.send(null);

3) 实现跨浏览器的CORS

1 functioncreateCORS(method, url){2     var xhr = newXMLHttpRequest();3     if('withCredentials' inxhr){4         xhr.open(method, url, true);5     }else if(typeof XDomainRequest != 'undefined'){6         var xhr = newXDomainRequest();7 xhr.open(method, url);8     }else{9         xhr = null;10 }11     returnxhr;12 }13 var request = createCORS('get', 'http://www.test.com');14 if(request){15     request.onload = function(){16 ......17 };18 request.send();19 }

方法六、使用location.hash+iframe来跨域(不常用)

假设域名test.com下的文件a.html要和csdnblogs.com域名下的b.html传递信息。
  1) 创建test.com下的a.html页面, 同时在a.html上加一个定时器,隔一段时间来判断location.hash的值有没有变化,一旦有变化则获取获取hash值,代码如下:

<script>
functionstartRequest(){var ifr = document.createElement('iframe');//创建一个隐藏的iframeifr.style.display = 'none';ifr.src= 'http://www.csdnblogs.com/b.html#paramdo';//传递的location.hash
document.body.appendChild(ifr);
}functioncheckHash() {try{var data = location.hash ? location.hash.substring(1):'';if(console.log) {console.log('Now the data is ' +data);}}catch(e) {};
}
setInterval(checkHash,5000);
window.onload=startRequest;</script>

2) b.html响应请求后再将通过修改a.html的hash值来传递数据,代码如下:

<script>
functioncheckHash() {var data = '';//模拟一个简单的参数处理操作switch(location.hash) {case '#paramdo':data= 'somedata';break;case '#paramset'://do something……break;default:break;}data&& callBack('#' +data);
}functioncallBack(hash) {//ie、chrome的安全机制无法修改parent.location.hash//所以要利用一个中间的www.csdnblogs.com域下的代理iframevar proxy = document.createElement('iframe');proxy.style.display= 'none';proxy.src= 'http://www.csdnblogs.com/c.html' +hash;//注意该文件在"www.csdnblogs.com"域下
document.body.appendChild(proxy);
}
window.onload=checkHash;</script>

3) test.com域下的c.html代码:

1 <script>
2 //因为parent.parent和自身属于同一个域,所以可以改变其location.hash的值
3 parent.parent.location.hash = self.location.hash.substring(1);4 </script>

方法七、使用Web sockets来跨域

web sockets: 是一种浏览器的API,它的目标是在一个单独的持久连接上提供全双工、双向通信。(同源策略对web sockets不适用)

web sockets原理:在JS创建了web socket之后,会有一个HTTP请求发送到浏览器以发起连接。取得服务器响应后,建立的连接会使用HTTP升级从HTTP协议交换为web sockt协议。

1 <script>
2 var socket = new WebSockt('ws://www.test.com');3 //http->ws; https->wss
4 socket.send('hello WebSockt');5 socket.onmessage = function(event){6     var data =event.data;7 }

方法八、使用flash URLLoader来跨域

flash有自己的一套安全策略,服务器可以通过crossdomain.xml文件来声明能被哪些域的SWF文件访问,SWF也可以通过API来确定自身能被哪些域的SWF加载。
例如:当跨域访问资源时,例如从域baidu.com请求域google.com上的数据,我们可以借助flash来发送HTTP请求。

跨域实现方式:
 

#1. 首先,修改域google.com上的crossdomain.xml(一般存放在根目录,如果没有需要手动创建) ,把baidu.com加入到白名单。
#2. 其次,通过Flash URLLoader发送HTTP请求
#3. 最后,通过Flash API把响应结果传递给JavaScript。

Flash URLLoader是一种很普遍的跨域解决方案,不过需要支持iOS的话,这个方案就不可行了。

以上八种方法,可以根据项目的实际情况来进行选择应用,个人认为window.name的方法既不复杂,也能兼容到几乎所有浏览器,这真是极好的一种跨域方法。

原文链接:https://blog.csdn.net/wangchengiii/article/details/78081032

转载于:https://www.cnblogs.com/lcspring/p/11079754.html

js处理的8种跨域方法相关推荐

  1. js中的几种跨域方法

    js跨域指的是通过js在不同域之间进行数据传输或通讯,例如ajax通信技术,或者通过js获取页面中iframe的数据.只要有任意一个不同,则协议.域名.端口中有任意一个不同,则彼此成为不同的域. 请注 ...

  2. js中几种实用的跨域方法原理详解

    这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...

  3. JavaScript 九种跨域方式实现原理

    前言 前后端数据交互经常会碰到请求跨域,什么是跨域,以及有哪几种跨域方式,这是本文要探讨的内容. 一.什么是跨域? 1.什么是同源策略及其限制内容? 同源策略是一种约定,它是浏览器最核心也最基本的安全 ...

  4. 九种跨域方式实现原理

    前言 前后端数据交互经常会碰到请求跨域,什么是跨域,以及有哪几种跨域方式,这是本文要探讨的内容. 本文完整的源代码请猛戳github 博客 一.什么是跨域? 1.什么是同源策略及其限制内容? 同源策略 ...

  5. JavaScript 九种跨域方式实现原理 1

    前言 前后端数据交互经常会碰到请求跨域,什么是跨域,以及有哪几种跨域方式,这是本文要探讨的内容. 一.什么是跨域? 1.什么是同源策略及其限制内容? 同源策略是一种约定,它是浏览器最核心也最基本的安全 ...

  6. 九种跨域方式的实现原理,第一个就超惊艳!| 技术头条

    作者 | 浪里行舟 责编 | 胡巍巍 前后端数据交互经常会碰到请求跨域,什么是跨域,以及有哪几种跨域方式,这正是本文要探讨的内容. 什么是跨域? 1.什么是同源策略及其限制内容? 同源策略是一种约定, ...

  7. JavaScript跨域方法

    一.什么是跨域 JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象.但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦.这里把涉及到跨域的一些问题简单地整理一下: ...

  8. 实现跨域访问---同源策略 、常见跨域方法

    实现跨域访问 同源策略 为了保证用户数据安全 防止恶意网站窃取数据 同源策略 三个行为限制: ​ Cookie.LocalStorage.indexDB无法读取 ​ DOM无法获取 ​ AJAX请求不 ...

  9. SSO的几种跨域方案

    在此只是记录一下自己在尝试SSO跨域实现的过程中学到的几种跨域方案,不包含任何例子和具体的实现方法. 最近在尝试SSO的跨域,看了好多资料,然后自己记录了一下可以实现的方法: ①跳转所有站点设置coo ...

  10. Spring Boot 中三种跨域场景总结

    文章目录 1.什么是跨域 2.解决方案 2.1 存在的问题 3.SpringSecurity 3.1 方式一 3.2 方式二 4.OAuth2 5.小结 跨域这个问题松哥之前写过文章,但是最近收到小伙 ...

最新文章

  1. [leetcode] Palindrome Number
  2. 有认知会推理!视觉大模型的未来不只靠表征
  3. 在winform程序里实现最小化隐藏到windows右下角
  4. Python常用的六款编程开发工具汇总!
  5. 为什么TCP连接要三次握手?
  6. python init函数可以外部调用么,如何从python类中调用外部函数
  7. CentOS7下使用yum安装MariaDB
  8. 更新计算机上的windows模块安装程序_Win10中用DOS命令也可以完成windows更新,这个技巧还真不知道...
  9. 酷Q萌萌机器人_GitHub - Titvt/CQRobot: 酷Q机器人——麦萌萌小管家
  10. Python:体脂计算
  11. Camunda与springboot集成入门实战
  12. 【项目管理/PMP/PMBOK第六版/新考纲】计算题! 项目章程/变更/工作绩效报告/项目范围说明书/工作分解结构WBS/最小浮动时间/挣值分析/采购
  13. 程序员面试必备的八大数据结构
  14. 电脑如何长截屏截图_持续集成截屏视频-DNRTV上的Jay Flowers和I
  15. 2020.2.18 大一寒假训练十一(set)
  16. js设置弹出式独立窗口页面,和 window 的方法
  17. Pic16f1828 1829串口收发
  18. 移动端vue实现部门结构功能_基于Vue制作组织架构树组件
  19. OpenStack T版—Nova组件部署详解
  20. 【Arduino实验02 LED流水灯】

热门文章

  1. Excel技能——批量生成excel的工作表名称目录链接
  2. 如何设计一份令人舒服的PPT
  3. 《暗时间》读书笔记与读后感
  4. 基于SpringBoot的在线问卷调查管理系统
  5. CDRX -- LTE连接态下的DRX
  6. java静态链表_Java数据结构-线性表之静态链表
  7. 利用偏最小二乘法选出最重要的特征波段Matlab
  8. excel切片器_干货分享:Excel数据透视表操作技巧,帮你提升工作效率
  9. 闲聊人工智能产品经理(AIPM)—人工智能产品经理的行业理解
  10. 获取贴图及IES文件