浏览器跨域访问解决方案

浏览器跨域访问解决方案

2015年11月4日 18972次浏览

跨域的概念

跨域大家都知道,不同地址,不同端口,不同级别,不同协议都会构成跨域。例如:about.haorooms.com和www.haorooms.com都会构成跨域。总结起来只要协议、域名、端口有任何一个不同,都被当作是不同的域。下面举例,每两个一组。

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

解决跨域的方案

上一篇文章,我写了window.postMessage,是一种跨域的解决方案。今天再介绍几个。

CORS跨域资源共享

众所周知,我们之前跨域很多时候用的是jsonp的方式,jsonp的方式我后面介绍。下面说说CORS跨域和jsonp跨域的优势:

CORS与JSONP相比,无疑更为先进、方便和可靠。

1、 JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。

2、 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。

3、 JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS。[低版本IE7以下不支持,要支持IE7还是要用jsonp方式]

CORS的使用

CORS要前后端同时做配置。

1、首先我们来看前端。

纯js的ajax请求。

<script type="text/javascript"> var xhr = new XMLHttpRequest(); //ie6以下用new ActiveXObject("Microsoft.XMLHTTP");可以做能力判断。 xhr.open("GET", "/haorooms",true); xhr.send(); </script>

以上的haorooms是相对路径,如果我们要使用CORS,相关Ajax代码可能如下所示:

<script type="text/javascript"> var xhr = new XMLHttpRequest();//ie6以下用new ActiveXObject("Microsoft.XMLHTTP");可以做能力判断。 xhr.open("GET", "http://www.haorooms.com/CORS",true); xhr.send(); </script>

当然,你也可以用jquery的ajax进行。

2、后端或者服务器端的配置

下面我们主要介绍Apache和PHP里的设置方法。

Apache:Apache需要使用mod_headers模块来激活HTTP头的设置,它默认是激活的。你只需要在Apache配置文件的 < Directory >, < Location>, < Files >或< VirtualHost>的配置里加入以下内容即可:

Header set Access-Control-Allow-Origin *

PHP:只需要使用如下的代码设置即可。

<?php  header("Access-Control-Allow-Origin:*");

以上的配置的含义是允许任何域发起的请求都可以获取当前服务器的数据。当然,这样有很大的危险性,恶意站点可能通过XSS攻击我们的服务器。所以我们应该尽量有针对性的对限制安全的来源,例如下面的设置使得只有www.haorooms.com这个域才能跨域访问服务器的API。

 Access-Control-Allow-Origin: http://www.haorooms.com 

通过jsonp跨域

jsonp跨域也需要前后端配合使用。一般后端设置callback ,前端给后台接口中传一个callback 就可以。

例如前端代码:

<script type="text/javascript"> function dosomething(jsondata){ //处理获得的json数据 } </script> <script src="http://haorooms.com/data.php?callback=dosomething"></script>

后台代码:

<?php
$callback = $_GET['callback'];//得到回调函数名 $data = array('a','b','c');//要返回的数据 echo $callback.'('.json_encode($data).')';//输出 ?>

假如你用ajax方式进行jsonp跨域,我之前的一篇文章中提及过:http://www.haorooms.com/post/jquery_ajax_wg

/*  
//简写形式,效果相同  
$.getJSON("url跨域地址",  {参数,要把callback作为参数传到后端},function(data){  //结构处理 
},"jsonp");  
*/  
$.ajax({ type : "get", url : "跨域地址", dataType : "jsonp",//数据类型为jsonp  jsonp: "callback",//服务端用于接收callback调用的function名的参数【后台接受什么参数,我们就传什么参数】我们上面设置是callback success : function(data){ //结果处理 }, error:function(data){ console.log(data); } });

通过修改document.domain来跨子域

我们只需要在跨域的两个页面中设置document.domain就可以了。修改document.domain的方法只适用于不同子域的框架间的交互。

例如:1.在页面 http:// www.haorooms.com/a.html 中设置document.domain

<iframe id = "iframe" src="http://haorooms.com/b.html" onload = "test()"></iframe> <script type="text/javascript"> document.domain = 'haorooms.com';//设置成主域 function test(){ alert(document.getElementById('iframe').contentWindow);//contentWindow 可取得子窗口的 window 对象 } </script>

2、在页面http:// haorooms.com/b.html 中设置document.domain

<script type="text/javascript"> document.domain = 'haorooms.com';//在iframe载入这个页面也设置document.domain,使之与主页面的document.domain相同 </script>

使用window.name来进行跨域

原理:

window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的。

方法:

假如有三个页面。

a.com/app.html:应用页面。 a.com/proxy.html:代理文件,一般是一个没有任何内容的html文件,需要和应用页面在同一域下。 b.com/data.html:应用页面需要获取数据的页面,可称为数据页面。

1、在应用页面(a.com/app.html)中创建一个iframe,把其src指向数据页面(b.com/data.html)。

数据页面会把数据附加到这个iframe的window.name上,data.html代码如下:

<script type="text/javascript"> window.name = 'I was there!'; // 这里是要传输的数据,大小一般为2M,IE和firefox下可以大至32M左右 // 数据格式可以自定义,如json、字符串 </script>

2、在应用页面(a.com/app.html)中监听iframe的onload事件,在此事件中设置这个iframe的src指向本地域的代理文件(代理文件和应用页面在同一域下,所以可以相互通信)。

app.html部分代码如下:

<script type="text/javascript"> var state = 0, iframe = document.createElement('iframe'), loadfn = function() { if (state === 1) { var data = iframe.contentWindow.name; // 读取数据 alert(data); //弹出'I was there!' } else if (state === 0) { state = 1; iframe.contentWindow.location = "http://a.com/proxy.html"; // 设置的代理文件 } }; iframe.src = 'http://b.com/data.html'; if (iframe.attachEvent) { iframe.attachEvent('onload', loadfn); } else { iframe.onload = loadfn; } document.body.appendChild(iframe); </script>

3、获取数据以后销毁这个iframe,释放内存;这也保证了安全(不被其他域frame js访问)。

<script type="text/javascript"> iframe.contentWindow.document.write(''); iframe.contentWindow.close(); document.body.removeChild(iframe); </script>

使用HTML5的window.postMessage方法跨域

转载于:https://www.cnblogs.com/libaoli/p/7879434.html

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

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

相关文章

oracle 分页

我直接贴代码了&#xff0c;做一个备份 public async zbjhList(request: Hapi.Request, h: Hapi.ResponseToolkit) {const { page, size } request.payload;const min (page - 1) * size;const max page * size;let sql SELECT * FROM (SELECT ROWNUM AS rowno, t.* FROM …

Android 2017-2018面试题详解

面试题&#xff08;固定答案不解答&#xff0c;自己可以找到&#xff09; 顺序是根据记忆排的&#xff0c;没有优先级之分&#xff0c;都是重点。 1.Activity的启动过程&#xff08;不要回答生命周期&#xff09; http://blog.csdn.net/luoshengyang/article/details/6689748…

docker查看容器并运行

1、查看所有容器 docker ps -a结果 2、运行容器 docker start 56b90db5253e

IE8 select 动态下拉遇到的问题

发生背景:经QC测试程序一直没问题,到客户测试竟然出现了下拉窗口失效. 检查发现客户用的IE ,360 浏览器都出现一样的问题,据说360是引用IE的核心. 看下IE版本是 8的..... 开发和QC都是11版本的... 经过一阵和度娘互动找到了下面原因 1.IE8不支持 onchanged 事件. 解决:使用…

cesium 设置地球默认区域为中国 一键返回默认区域

直接上代码啦 Cesium.Camera.DEFAULT_VIEW_RECTANGLE Cesium.Rectangle.fromDegrees(90, -20, 110, 90); const viewer new Cesium.Viewer(cesiumContainer, { selectionIndicator: false,infoBox: false,animation: false,baseLayerPicker: false,timeline: false,geocoder…

Spring boot Tomcat配置

来自: https://www.cnblogs.com/a8457013/p/7687764.html转载于:https://www.cnblogs.com/eason-d/p/7884307.html

js 快捷键

直接上代码 document.onkeydown onKeyDown; function onKeyDown() {if (window.event.ctrlKey && (window.event.keyCode 69)) {alert("ctrle");} }键码值如下 字母和数字键的键码值(keyCode)按键键码按键键码按键键码按键键码A65J74S83149B66K75T84250C…

Android 属性动画ObjectAnimator使用demo,组合动画

//第一个参数&#xff1a;指定执行动画的控件&#xff0c;第二个参数&#xff1a;指定控件的属性&#xff0c;第三个参数是可变长参数 public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) 动画过程监听 animator2.addUpdateListen…

清除输入框缓存数据

如果不想让浏览器缓存input的值&#xff0c;有2种方法&#xff1a; 方法一&#xff1a; <input type"text" autocomplete"off" name"test" /> 方法二&#xff1a; <form action"#" autocomplete"off"><inpu…

Android 自定义操作成功的loading动画

1、res---->values文件夹下添加文件attrs.xml详情如下&#xff1a; <?xml version"1.0" encoding"utf-8"?> <resources><declare-styleable name"SuccessView"><attr name"svStrokeColor" format"col…

cesium的clock开始,结束,控制速率

开始 viewer.clock.shouldAnimate true; 结束 window.viewer.clock.shouldAnimate false;速率调整 viewer.clock.multiplier 8;

Android 下载进度条, 自定义加载进度条,loading动画

1、自定义loadingline动画 /*** 作者&#xff1a;created by meixi* 邮箱&#xff1a;13164716840163.com* 日期&#xff1a;2018/9/6 10*/public class LoadingLine extends View {private Paint paint;private Paint backPaint;private Paint textPaint;private boolean ini…

eslint airbnb 不允许尾随逗号

我使用的是airbnb规则进行代码eslint。 会出现保存后&#xff0c;数组或者对象最后一个元素尾随逗号。 此时需要在.eslintrc.js中加入下面代码即可 "comma-dangle": ["error", {"arrays": "never","objects": "never…

我的物联网项目(十二) 单体应用架构不行?

单体应用架构在创业型项目里面是非常合适的&#xff0c;毕竟它主要的担当还是在验证创业模式以及迅速功能实现&#xff0c;所以它从开发到部署&#xff0c;在少量开发人员的基础上能非常减少成本&#xff0c;主要是门槛低&#xff0c;开发效率也非常高。到目前为此&#xff0c;…