前端解决跨域问题的8种方案

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

1.同源策略如下:

URL说明是否允许通信
http://www.a.com/a.js
http://www.a.com/b.js
同一域名下允许
http://www.a.com/lab/a.js
http://www.a.com/script/b.js
同一域名下不同文件夹允许
http://www.a.com:8000/a.js
http://www.a.com/b.js
同一域名,不同端口不允许
http://www.a.com/a.js
https://www.a.com/b.js
同一域名,不同协议不允许
http://www.a.com/a.js
http://70.32.92.74/b.js
域名和域名对应ip不允许
http://www.a.com/a.js
http://script.a.com/b.js
主域相同,子域不同不允许
http://www.a.com/a.js
http://a.com/b.js
同一域名,不同二级域名(同上)不允许(cookie这种情况下也不允许访问)
http://www.cnblogs.com/a.js
http://www.a.com/b.js
不同域名不允许

特别注意两点:

第一,如果是协议和端口造成的跨域问题“前台”是无能为力的,

第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。

“URL的首部”指window.location.protocol +window.location.host,也可以理解为“Domains, protocols and ports must match”。

2. 前端解决跨域问题

1> document.domain + iframe      (只有在主域相同的时候才能使用该方法)

1) 在www.a.com/a.html中:

复制代码

document.domain = 'a.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://www.script.a.com/b.html';
ifr.display = none;
document.body.appendChild(ifr);
ifr.onload = function(){var doc = ifr.contentDocument || ifr.contentWindow.document;//在这里操作doc,也就是b.htmlifr.onload = null;
};

复制代码

2) 在www.script.a.com/b.html中:

document.domain = 'a.com';

 

2> 动态创建script

这个没什么好说的,因为script标签不受同源策略的限制。

复制代码

function loadScript(url, func) {var head = document.head || document.getElementByTagName('head')[0];var script = document.createElement('script');script.src = url;script.onload = script.onreadystatechange = function(){if(!this.readyState || this.readyState=='loaded' || this.readyState=='complete'){func();script.onload = script.onreadystatechange = null;}};head.insertBefore(script, 0);
}
window.baidu = {sug: function(data){console.log(data);}
}
loadScript('http://suggestion.baidu.com/su?wd=w',function(){console.log('loaded')});
//我们请求的内容在哪里?
//我们可以在chorme调试面板的source中看到script引入的内容

复制代码

 

3> location.hash + iframe

原理是利用location.hash来进行传值。

假设域名a.com下的文件cs1.html要和cnblogs.com域名下的cs2.html传递信息。
1) cs1.html首先创建自动创建一个隐藏的iframe,iframe的src指向cnblogs.com域名下的cs2.html页面
2) cs2.html响应请求后再将通过修改cs1.html的hash值来传递数据
3) 同时在cs1.html上加一个定时器,隔一段时间来判断location.hash的值有没有变化,一旦有变化则获取获取hash值
注:由于两个页面不在同一个域下IE、Chrome不允许修改parent.location.hash的值,所以要借助于a.com域名下的一个代理iframe

代码如下:
先是a.com下的文件cs1.html文件:

复制代码

function startRequest(){var ifr = document.createElement('iframe');ifr.style.display = 'none';ifr.src = 'http://www.cnblogs.com/lab/cscript/cs2.html#paramdo';document.body.appendChild(ifr);
}function checkHash() {try {var data = location.hash ? location.hash.substring(1) : '';if (console.log) {console.log('Now the data is '+data);}} catch(e) {};
}
setInterval(checkHash, 2000);

复制代码

cnblogs.com域名下的cs2.html:

复制代码

//模拟一个简单的参数处理操作
switch(location.hash){case '#paramdo':callBack();break;case '#paramset'://do something……break;
}function callBack(){try {parent.location.hash = 'somedata';} catch (e) {// ie、chrome的安全机制无法修改parent.location.hash,// 所以要利用一个中间的cnblogs域下的代理iframevar ifrproxy = document.createElement('iframe');ifrproxy.style.display = 'none';ifrproxy.src = 'http://a.com/test/cscript/cs3.html#somedata';    // 注意该文件在"a.com"域下document.body.appendChild(ifrproxy);}
}

复制代码

a.com下的域名cs3.html

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

 

4> window.name + iframe

window.name 的美妙之处:name 值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。

1) 创建a.com/cs1.html

2) 创建a.com/proxy.html,并加入如下代码

复制代码

<head><script>function proxy(url, func){var isFirst = true,ifr = document.createElement('iframe'),loadFunc = function(){if(isFirst){ifr.contentWindow.location = 'http://a.com/cs1.html';isFirst = false;}else{func(ifr.contentWindow.name);ifr.contentWindow.close();document.body.removeChild(ifr);ifr.src = '';ifr = null;}};ifr.src = url;ifr.style.display = 'none';if(ifr.attachEvent) ifr.attachEvent('onload', loadFunc);else ifr.onload = loadFunc;document.body.appendChild(iframe);}
</script>
</head>
<body><script>proxy('http://www.baidu.com/', function(data){console.log(data);});</script>
</body>

复制代码

3 在b.com/cs1.html中包含:

<script>window.name = '要传送的内容';
</script>

 

5> postMessage(HTML5中的XMLHttpRequest Level 2中的API)

1) a.com/index.html中的代码:

复制代码

<iframe id="ifr" src="b.com/index.html"></iframe>
<script type="text/javascript">
window.onload = function() {var ifr = document.getElementById('ifr');var targetOrigin = 'http://b.com';  // 若写成'http://b.com/c/proxy.html'效果一样// 若写成'http://c.com'就不会执行postMessage了ifr.contentWindow.postMessage('I was there!', targetOrigin);
};
</script>

复制代码

2) b.com/index.html中的代码:

复制代码

<script type="text/javascript">window.addEventListener('message', function(event){// 通过origin属性判断消息来源地址if (event.origin == 'http://a.com') {alert(event.data);    // 弹出"I was there!"alert(event.source);  // 对a.com、index.html中window对象的引用// 但由于同源策略,这里event.source不可以访问window对象}}, false);
</script>

复制代码

6> CORS

CORS背后的思想,就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。

IE中对CORS的实现是xdr

复制代码

var xdr = new XDomainRequest();
xdr.onload = function(){console.log(xdr.responseText);
}
xdr.open('get', 'http://www.baidu.com');
......
xdr.send(null);

复制代码

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

复制代码

var xhr =  new XMLHttpRequest();
xhr.onreadystatechange = function () {if(xhr.readyState == 4){if(xhr.status >= 200 && xhr.status < 304 || xhr.status == 304){console.log(xhr.responseText);}}
}
xhr.open('get', 'http://www.baidu.com');
......
xhr.send(null);

复制代码

实现跨浏览器的CORS

复制代码

function createCORS(method, url){var xhr = new XMLHttpRequest();if('withCredentials' in xhr){xhr.open(method, url, true);}else if(typeof XDomainRequest != 'undefined'){var xhr = new XDomainRequest();xhr.open(method, url);}else{xhr = null;}return xhr;
}
var request = createCORS('get', 'http://www.baidu.com');
if(request){request.onload = function(){......};request.send();
}

复制代码

7> JSONP

JSONP包含两部分:回调函数和数据。

回调函数是当响应到来时要放在当前页面被调用的函数。

数据就是传入回调函数中的json数据,也就是回调函数的参数了。

复制代码

function handleResponse(response){console.log('The responsed data is: '+response.data);
}
var script = document.createElement('script');
script.src = 'http://www.baidu.com/json/?callback=handleResponse';
document.body.insertBefore(script, document.body.firstChild);
/*handleResonse({"data": "zhe"})*/
//原理如下:
//当我们通过script标签请求时
//后台就会根据相应的参数(json,handleResponse)
//来生成相应的json数据(handleResponse({"data": "zhe"}))
//最后这个返回的json数据(代码)就会被放在当前js文件中被执行
//至此跨域通信完成

复制代码

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

1)安全问题(请求代码中可能存在安全隐患)

2)要确定jsonp请求是否失败并不容易

8> web sockets

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

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

只有在支持web socket协议的服务器上才能正常工作。

var socket = new WebSockt('ws://www.baidu.com');//http->ws; https->wss
socket.send('hello WebSockt');
socket.onmessage = function(event){var data = event.data;
}

 

 

 

转载于:https://my.oschina.net/u/2246951/blog/838428

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/396745.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

k歌的录音伴奏合成技术如何实现_K歌神器,用唱吧麦克风攀登天籁高峰

自从喜欢上了手机K歌&#xff0c;经常会上传一些自己的作品&#xff0c;起初无论音质如何都是乐在其中&#xff0c;可时间久了发现回放效果确实不如那榜单上的高手&#xff0c;究其原因想到了麦克风&#xff0c;网上一搜果然有各种K歌辅助工具&#xff0c;多番对比之下&#xf…

android点击左上角划出,使用Android中的Path和RectF在左上角右上角左下角绘制圆角...

有一个Path#addRoundRect()重载,它接受一个包含八个值的float数组,其中我们可以为四个角中的每一个指定x和y半径.这些值为[x,y]对,从左上角开始,顺时针绕其余部分.对于我们想要舍入的那些角,我们将该对的两个值都设置为半径值,并将它们保留为零,而不是那些.作为一个说明性示例,…

Nodejs微信开发

因为使用了Bot Framework开发了一个小功能&#xff0c;它目前支持了Skype\Teams\Slack等&#xff0c;但在国内来讲&#xff0c;微信还是一个比较流行的软件&#xff0c;所以需要接上微信 原来开发Bot的时候使用的是.Net开发的&#xff0c;这次我决定使用Nodejs开发一个简单的后…

性别有什么用_为啥不让男孩玩布娃娃?别让你的“性别偏见”,给孩子的人生设限...

在养育孩子的过程中&#xff0c;父母总是会犯许多错误&#xff0c;更是有一些错误会直接使孩子毁掉一生&#xff0c;而性别偏见正是很多家长都会去犯的错误&#xff0c;对男孩和女孩有着刻板印象&#xff0c;也正是因为这一点使孩子的潜力和天赋被压制。前几天我带着孩子去逛商…

android的时间代码怎么写,Android 日期和时间的使用实例详解

Android 日期和时间的使用日期和时间的使用&#xff1b;1&#xff1a;弹出框TimePickerDialog,DatePickerDialog2&#xff1a;组件TimePicker,DatePickerTimePickerDialog的使用&#xff1a;通过点击button显示图一&#xff0c;然后用户可以设置时间DatePickerDialog的使用只需…

andriod studio 查看项目依赖_Intellij IDEA 中如何查看maven项目中所有jar包的依赖关系图...

Maven 组件界面介绍如上图标注 1 所示&#xff0c;为常用的 Maven 工具栏&#xff0c;其中最常用的有&#xff1a;第一个按钮&#xff1a;Reimport All Maven Projects 表示根据 pom.xml 重新载入项目。一般单我们在 pom.xml 添加了依赖包或是插件的时候&#xff0c;发现标注 4…

Kurento协议

2019独角兽企业重金招聘Python工程师标准>>> Kurento媒体服务器可以被两种外部Kurento客户端控制&#xff0c;如Java或JavaScript。这些客户端使用Kuernto协议来和KMS通信。Kurento 协议是基于WebSocket协议&#xff0c;并使用了JSON-RPC V2.0 消息来提交请求和发送…

升级php7_PhpStorm 2019.3 发布,全面支持 PHP 7.4

PhpStorm 2019.3 发布了&#xff0c;这个版本主要集中在性能和质量上&#xff0c;旨在提供一个更稳定、更快的 IDE。PhpStorm 2019.3 全面支持 PHP 7.4&#xff0c;还带来 PSR-12 代码样式&#xff0c;用于远程解释器的 WSL&#xff0c;MongoDB 支持&#xff0c;HTTP 客户端更新…

ftp 客户端 使用http代理 源码_代理服务器连接HTTPS过程

说到HTTPS代理很多人瞬间就会联想到HTTPS的各种证书和各种加密&#xff0c;觉得很高端很复杂的样子。其实不然&#xff0c;代理服务器不需要配置证书、也不需要处理任何加密。因为HTTPS代理是通过Web隧道(Web tunnel)工作的。Web隧道允许用户通过HTTP连接发送非HTTP流量(例如FT…

python解zuobiaoxi方程_Python还能解决数学相关问题?大学生:以后就靠他了,事半功倍...

问题背景高等数学应用非常广&#xff0c;基本上涉及到函数的地方都要用到微积分&#xff0c;还有在几何方面也是如此&#xff0c;计算机的应用让我们能简单快速处理各种高等数学中的计算&#xff0c;比如极限、导数、积分、微分方程等的计算。实验目的使用 Python 通过计算与作…

基础正则表达式介绍与练习

基础正则表达式介绍与练习 一、什么是正则表达式 在做文字处理或编写程序时&#xff0c;用到查找、替换等功能&#xff0c;使用正则表达式能够简单快捷的完成目标。简单而言&#xff0c;正则表达式通过一些特殊符号的帮助&#xff0c;使用户可以轻松快捷的完成查找、删除、替换…

android canvas 网络图,【巨坑:toDataURL】canvas合成网络图片

不知有没有小伙伴用过canvas合成图片&#xff0c;然后爆炸报错截图尼玛&#xff0c;然后各种搜索&#xff0c;不外乎以下几种坑爹处理方案&#xff1a;后端处理&#xff0c;比如Access-Control-Allow-Origin "*"(要是请求到其他网站的图片就不适用了&#xff0c;比如…

水晶报表如何查看sql_有了这个报表工具,一键生成自定义的各种报表,还可以导出Excel...

EasyReport是一个简单易用的Web报表工具,它的主要功能是把SQL语句查询出的数据转换成报表页面&#xff0c; 同时支持表格的跨行(RowSpan)与跨列(ColSpan)配置。 同时它还支持报表Excel导出、图表显示及固定表头与左边列的功能。功能介绍本工具从数据库(MySQL,Oracle,SQLServer,…

Sitemesh3的使用及配置

1 . Sitemesh 3 简介 Sitemesh 是一个网页布局和修饰的框架&#xff0c;基于 Servlet 中的 Filter&#xff0c;类似于 ASP.NET 中的‘母版页’技术。参考&#xff1a;百度百科&#xff0c;相关类似技术&#xff1a;Apache Tiles。 官网&#xff1a;http://wiki.sitemesh.org/wi…

鸿蒙系统r如何升级,高歌猛进,鸿蒙系统升级机型再次确认,花粉:终等到!...

虽然华为手机现在的压力非常大&#xff0c;但是在前进的道路上&#xff0c;真的充满了乐观精神&#xff0c;而且现在也算是一路高歌猛进了&#xff0c;发展路线开始加快了许多&#xff0c;无论是新机还是系统&#xff0c;都有着非常多的新消息。因为华为手机的实力很强&#xf…

android studio背景模糊_[Android翻译]CameraX:过去、现在和未来的一瞥

CameraX是一个未捆绑的Android Jetpack库&#xff0c;它可以帮助你在Android应用中轻松添加摄像头功能。传统上&#xff0c;由于Android设备种类繁多&#xff0c;编程模型复杂&#xff0c;在Android上构建具有相机功能的应用程序非常困难。现在成千上万的开发者都在使用CameraX…

export function函数传参_04 js高阶函数(惰性函数、柯里化函数、compose函数)和单例设计模式...

高阶函数的定义在《javascript设计模式和开发实践》中是这样定义的。函数可以作为参数被传递&#xff1b;函数可以作为返回值输出。结合这两个特点&#xff0c;首先想到的肯定是回调函数&#xff0c;回调函数也是高阶函数的一种&#xff0c;除了回调函数&#xff0c;还有很多的…

mysql相关命令操作

2019独角兽企业重金招聘Python工程师标准>>> 远程连接容器中的mysql&#xff1a;mysql -h 192.168.5.116 -P 3306 -u root -p123456 启动mysql容器&#xff1a; $ sudo docker pull mysql:5.6.35 $ sudo docker run --name mysql -p 12345:3306 -e MYSQL_ROOT_PASSW…

html实体注册商标,html 注册商标,html 注册商标代码

html中注册的页面用什么标签写好对于html中的注册页面&#xff0c;策朋专业办理商标注册、专利申请、版权登记保护&#xff0c;需要一个表格。使用标签&#xff0c;输入和按钮标签来组合成就。使用html作为注册页面。实际上&#xff0c;只要您能达到期望的效果&#xff0c;它的…

java已知一个二叉树_#二叉树复习#

#二叉树复习#目录满二叉树完全二叉树平衡二叉树二叉树的主要性质--二叉树的度--二叉树的深度计算二叉树的遍历其他符号变量结点总数深度度为0的结点数/叶子结点数度为1的结点数度为2的结点数什么是满二叉树&#xff1f;二叉树每层的结点数为。满二叉树总结点数&#xff1a;。图…