JS中的八种常用的跨域方式及其具体示例的总结(最新、最完整、最详细)

JS中的八种常用的跨域方式及其具体示例的总结

  这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据。
  跨域问题是由于javascript语言安全限制中的同源策略造成的。
  简单来说,同源策略是指一段脚本只能读取来自同一来源的窗口和文档的属性,这里的同一来源指的是域名、协议和端口号的组合只要协议、域名、端口有任何一个不同,都被当作是不同的域。

下表给出了相对http:// www.a.com/dir/a.html同源检测的结果:

JS中的八种常用的跨域方式及其具体示例的总结(最新、最完整、最详细)_第1张图片

特别注意两点:

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

URL的首部:指window.location.protocol +window.location.host,也可以理解为“Domains(域名), protocols(协议) and ports(端口) must match”。

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

方法一、通过jsonp跨域

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

/*handleResonse({"data": "zhe"})*/
//原理如下:
//当我们通过script标签请求时
//后台就会根据相应的参数(json,handleResponse)
//来生成相应的json数据(handleResponse({"data": "zhe"}))
//最后这个返回的json数据(代码)就会被放在当前js文件中被执行
//至此跨域通信完成
//1、使用JS动态生成script标签,进行跨域操作
function handleResponse(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标签
function handleResponse(response){
    console.log('The responsed data is: '+response.data);
    //处理获得的Json数据
}

--------------------------
//3、使用jQuery进行jsonp操作
//jquery会自动生成一个全局函数来替换callback=?中的问号,之后获取到数据后又会自动销毁
//$.getJSON方法会自动判断是否跨域,不跨域的话,就调用普通的ajax方法;跨域的话,则会以异步加载js文件的形式来调用jsonp的回调函数。

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中的东西的:

//  http://www.example.com/a.html 页面中
<script>
function onLoad(){
    var iframe = document.getElementById('iframe');
    var win = iframe.contentWindow;
    //这里能够获取到iframe中的window对象,但是window对象的属性和方法几乎不可用。
    var doc = win.document;//这里获取不到iframe中的document对象
    var name = win.name;//这里获取不到window对象的name属性
    ······
}