js中跨域方法

同源策略(协议+端口号+域名要相同)

1、jsonp跨域(只能解决get)

原理:动态创建一个script标签。利用script标签的src属性不受同源策略限制,因为所有的src属性和href属性都不受同源策略的限制,可以请求第三方服务器资源内容

步骤: 1).去创建一个script标签

2).script的src属性设置接口地址

3).接口参数,必须要带一个自定义函数名,要不然后台无法返回数据

4).通过定义函数名去接受返回的数据

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

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

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

缺点:

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

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

2、document.domain 基础域名相同,子域名不同

浏览器同源策略限制:

#(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中的东西的。所以我们就要用到document.domain

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

<iframe src = "http://script.a.com/dir/b.html" id="iframe" onload = "loLoad()"></iframe>

<script>

document.domain = "a.com";//设置成主域

function test(){

    var iframe = document.getElementById("iframe");

    var win = iframe.contentWindow;

    //在这里就可以操作b.html

}

</script>

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

只能把document.domain设置成自身或更高一级的父域,且主域必须相同。

例如:a.b.c.com 中某个文档的document.domain 可以设成a.b.c.com、b.c.com 、c.com中的任意一个。


3、window.name 利用在一个浏览器窗口内,载入所有的域名都是共享一个window.name

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

正是由于window的name属性的特征,所以可以使用window.name来进行跨域。

举例:

1)在一个a.html页面中,有如下代码:

<script>

    window.name = "哈哈,我是页面a设置的值哟!";

    //设置window.name的值

    setTimeout(function(){

        window.location = 'b.html';

    },3000);//3秒后把一个新页面载入当前window

</script>

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

<script>

    alert(window.name);//读取window.name的值

<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代码:

<script>

    function getData(){

    //iframe载入data.html页面会执行此函数

        var ifr = document.getElementById("iframe");

        ifr.onload = function(){

        //这个时候iframe和a.html已经处于同一源,可以互相访问

            var data = ifr.contentWindow.name;

//获取iframe中的window.name,也就是data.html中给它设置的数据

            alert(data);

        }

        ifr.src = 'b.html';//这里的b.html为随便一个页面,只要与a.html同源就行,目的是让a.html能够访问到iframe中的东西,否则访问不到

    }

</script>

<iframe id = "iframe" src = "cnblogs.com/data.html" style = "display:none" onload = "getData()"></iframe>

2)创建example.com/a.html的代码:

<script>

    function getData(){

    //iframe载入data.html页面会执行此函数

        var ifr = document.getElementById("iframe");

        ifr.onload = function(){

        //这个时候iframe和a.html已经处于同一源,可以互相访问

            var data = ifr.contentWindow.name;

//获取iframe中的window.name,也就是data.html中给它设置的数据

            alert(data);

        }

        ifr.src = 'b.html';//这里的b.html为随便一个页面,只要与a.html同源就行,目的是让a.html能够访问到iframe中的东西,否则访问不到

    }

</script>

<iframe id = "iframe" src = "cnblogs.com/data.html" style = "display:none" onload = "getData()"></iframe>

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

<script>

    function getData(){

    //iframe载入data.html页面会执行此函数

        var ifr = document.getElementById("iframe");

        ifr.onload = function(){

        //这个时候iframe和a.html已经处于同一源,可以互相访问

            var data = ifr.contentWindow.name;

//获取iframe中的window.name,也就是data.html中给它设置的数据

            alert(data);

        }

        ifr.src = 'b.html';//这里的b.html为随便一个页面,只要与a.html同源就行,目的是让a.html能够访问到iframe中的东西,否则访问不到

    }

</script>

<iframe id = "iframe" src = "cnblogs.com/data.html" style = "display:none" onload = "getData()"></iframe>

4、使用跨域资源共享(CORS)来跨域

CORS:一种跨域访问的机制,可以让AJAX实现跨域访问;CORS允许一个域上的网络应用向另一个域提交跨域AJAX请求。

原理:服务器设置Access-Control-Allow-Origin HTTP响应头之后,浏览器将会允许跨域请求.

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

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

var xdr = new XDomainRequest();

xdr.onload = function(){

    console.log(xdr.responseText);

}

xdr.open('get', 'http://www.test.com');

......

xdr.send(null);

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

var xhr = new XMLHttpRequest();

xhr.onreadystatechange = function () {

  if(xhr.readyState === 4 && xhr.status === 200){

        console.log(xhr.responseText);

        }

    }

}

xhr.open('get', 'http://www.test.com');

......

xhr.send(null);

3) 实现跨浏览器的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.test.com');

if(request){

    request.onload = function(){

        ......

    };

    request.send();

}

5、利用h5新特性window.postMessage()

window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源(可实现跨域),目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。

message:为要发送的消息,类型只能为字符串;

targetOrigin:用来限定接收消息的那个window对象所在的域,如果不想限定域,可以使用通配符 “*”。

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

<script>

function onLoad(){

    var iframe = document.getElementById("iframe");

    var win = iframe.contentWindow;

    win.postMessage('哈哈,我是来自页面a.html的信息哟!','*');//向不同域的www.script.com/b.html发送消息

}

</script>

<iframe id="iframe" src="www.script.com/b.html" onload="onLoad()"></iframe>

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

<script>

window.onmessage = function (e) {

e = e || event ;

alert (e.data);

}

</script>

优点:使用postMessage来跨域传送数据还是比较直观和方便的; 

缺点: IE6、IE7不支持,所以用不用还得根据实际需要来决定。




©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,884评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,212评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,351评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,412评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,438评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,127评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,714评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,636评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,173评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,264评论 3 339
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,402评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,073评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,763评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,253评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,382评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,749评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,403评论 2 358

推荐阅读更多精彩内容