企业网站,个人博客等WordPress网站以及其他语言网站开发定制需求加QQ详聊。

关于浏览器的跨域问题实用方法总结

JavaScript笔记 码云 42℃ 0评论

对于刚入行的前端同学,跨域问题一直困扰大家,在实际项目中总会遇到跨域问题,如何解决跨域问题呢?于是在网上搜罗了很多关于跨域解决方法,但都不是让我满意,所以今天抽时间为大家总结一下我们最常用的跨域解决方案,在这之前我们么先要明白什么是跨域?

跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器施加的安全限制。

所谓同源是指,域名,协议,端口均相同。

例如:about.mybj123.com和www.mybj123.com都会构成跨域。总结起来只要协议、域名、端口有任何一个不同,都被当作是不同的域。不明白没关系,下面举个栗子,每两个一组。

URL                                                                          说明                                           是否允许通信

http://www.mybj123.com/a.js

http://www.mybj123.com/b.js                          同一域名下                                           允许

http://www.mybj123.com/lab/a.js

http://www.mybj123.com/script/b.js               同一域名下不同文件夹                          允许

http://www.mybj123.com:8000/a.js

http://www.mybj123.com/b.js                          同一域名,不同端口不                          允许

http://www.mybj123.com/a.js

https://www.mybj123.com/b.js                        同一域名,不同协议不                          允许

http://www.mybj123.com/a.js

http://60.32.92.74/b.js                                         域名和域名对应ip不                               允许

http://www.mybj123.com/a.js

http://about.mybj123.com/b.js                       主域相同,子域不同不                            允许

http://www.mybj123.com/a.js

http://mybj123.com/b.js                                  同一域名,不同二级域名(同上)          不允许(cookie这种情况下也不允许访问)

http://www.hao123.com/a.js

http://www.mybj123.com/b.js                         不同域名                                                  不允许

跨域方法:

在之前我写过一篇html5postMessagede在两个页面之间的跨域通信问题,这是一种快解决方案,接下来再介绍几种。

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=newXMLHttpRequest();//ie6以下用newActiveXObject("Microsoft.XMLHTTP");可以做能力判断。

  xhr.open("GET","/mybj123",true);

  xhr.send();

  </script>

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

<script type="text/javascript">

  var xhr=newXMLHttpRequest();//ie6以下用newActiveXObject("Microsoft.XMLHTTP");可以做能力判断。

  xhr.open("GET","http://www.mybj123.com/CORS",true);

  xhr.send();

  </script>

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

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

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

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

HeadersetAccess-Control-Allow-Origin*

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

<?php

header(“Access-Control-Allow-Origin:*”);

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

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

通过jsonp跨域

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

例如前端代码:

<script type="text/javascript">

  function dosomething(jsondata){

  //处理获得的json数据

  }

  </script>

  <script src="http://mybj123.com/data.php?callback=dosomething"></script>

后台代码:

<?php

  $callback=$_GET['callback'];//得到回调函数名

  $data=array('a','b','c');//要返回的数据

  echo $callback.'('.json_encode($data).')';//输出

  ?>

假如你用ajax方式进行jsonp跨域,我之前的一篇文章中提及过:http://www.mybj123.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.mybj123.com/a.html中设置document.domain

<iframe id="iframe" src="http://mybj123.com/b.html" onload="test()"></iframe>

  <script type="text/javascript">

  document.domain='mybj123.com';//设置成主域

  functiontest(){

  alert(document.getElementById('iframe').contentWindow);//contentWindow可取得子窗口的window对象

  }

  </script>

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

<script type="text/javascript">

  document.domain='mybj123.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代码如下:

<scripttype=”text/javascript”>

window.name=’Iwasthere!’;//这里是要传输的数据,大小一般为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);//弹出'Iwasthere!'

  }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,释放内存;这也保证了安全(不被其他域framejs访问)。

<script type="text/javascript">

  iframe.contentWindow.document.write('');

  iframe.contentWindow.close();

  document.body.removeChild(iframe);

  </script>

结束语:

以上就是今天为大家带来的跨域解决方法总结,总有一款适合你,内容有什么不当之处,欢迎来稿之巅,也可以在下方留言共同探讨。

转载请注明:码云笔记 » 关于浏览器的跨域问题实用方法总结

喜欢 (2)or分享 (0)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址