跨域解决方案总结

同源策略

浏览器为了保证用户信息的安全,防止恶意网站窃取数据,禁止不同域之间的JS进行交互。
对于浏览器而言,只要域名、协议、端口中有一个不同就会引发同源策略。

同源策略限制以下行为:
1.Cookie、LocalStorage 和 IndexDB 无法读取
2.DOM 和 JS 对象无法获取
3.Ajax请求无法发送

跨域场景

在这里插入图片描述

跨域解决方案

1. JSONP

为了减轻web服务器的负载,JS、CSS、img等静态资源会被放在CDN服务器上,不同源也会被浏览器允许加载。
JSONP就是利用了这个原理,动态创建一个script标签,通过src引入一个JS脚本文件,这个文件的内容是一个函数调用,参数是服务器返回的数据。需在页面定义好回调函数来处理返回的数据。

不足之处
只能使用GET方法,不能使用POST方法。
不能进行JSONP调用的错误处理。

2.CORS

CORS的全称是跨域资源共享。它是一个W3C标准,允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

使用方式
在服务端设置Access-Control-Allow-Origin响应头。
(1)简单请求
请求方式属于HEAD GET POST

HTTP头信息不超出
Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type

发现是简单请求,浏览器在头信息中增加一个origin字段,用来说明本次请求来自哪个源。服务器根据这个值决定是否同意。

(2)非简单请求
复杂请求的请求方式是PUT或DELETE

复杂请求会在通信前加一次预检请求,使用OPTIONS方法表示该请求用于询问,询问服务器当前域名是否在许可名单中,得到肯定后才会发出正式的http请求。

优点
CORS支持所有类型的请求。
开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。
缺点
兼容性差,IE10以上才支持。

3.document.domain+iframe

两个页面都通过js强制设置document.domain为基础主域,就实现了同域。这种方法仅限主域相同的情况。

使用方法
比如在 www.domain.com/a.html 的页面里要访问 www.domain.com/b.html 里面的东西。

父窗口:(www.domain.com/a.html)

<iframe id="iframe" src="http://child.domain.com/b.html"></iframe>
<script>
    document.domain = 'domain.com';
    var user = 'admin';
</script>

子窗口:(www.domain.com/b.html)

<script>
    document.domain = 'domain.com';
    // 获取父窗口中变量
    alert('get js data from parent ---> ' + window.parent.user);
</script>

4.location.hash+iframe

a欲与b跨域相互通信,通过中间页c来实现。 三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。

5.window.name+iframe

name值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值。
浏览器跨域iframe禁止互相调用或传值。但是调用iframe时,window.name却不变,正是利用这个特性来互相传值,当然跨域下是不允许读取iframe的window.name值。所以我们还需要加一个空的代理页面(与主页面同域)

使用方法
(1)先准备好主页面、数据页面和代理页面。
  http://www.a.com/main.html //主页面

http://www.a.com/other.html // 代理页面,要求和应用页面在同一个域。一般是一个空的html。

http://www.b.com/data.html //应用页面获取数据的页面,简称:数据页面
(2) 数据页面将数据传到window.name中去。
window.name=“string”; //可以是其他类型的数据,比如数组,对象等等。
(3)主页面通过代理页面读取数据。

6.postMessage()

这是H5的新特性,是一个发送消息的API。
可以解决以下问题:
(1)页面和其打开的新窗口的数据传递
(2)多窗口之间消息传递
(3)页面与嵌套的iframe消息传递
(4)上面三个场景的跨域数据传递

使用方法
postMessage(data,origin)方法接受两个参数
data: html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用JSON.stringify()序列化。
origin: 协议+主机+端口号,也可以设置为"*",表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。

主页面:

<iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"></iframe>
<script>       
    var iframe = document.getElementById('iframe');
    iframe.onload = function() {
        var data = {
            name: 'aym'
        };
        // 向domain2传送跨域数据
        iframe.contentWindow.postMessage(JSON.stringify(data), 'http://www.domain2.com');
    };

    // 接受domain2返回数据
    window.addEventListener('message', function(e) {
        alert('data from domain2 ---> ' + e.data);
    }, false);
</script>

数据页面:

<script>
    // 接收domain1的数据
    window.addEventListener('message', function(e) {
        alert('data from domain1 ---> ' + e.data);

        var data = JSON.parse(e.data);
        if (data) {
            data.number = 16;

            // 处理后再发回domain1
            window.parent.postMessage(JSON.stringify(data), 'http://www.domain1.com');
        }
    }, false);
</script>

7.nginx代理

同源策略是浏览器的安全策略,不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨越问题。

通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。

8.websocket

WebSocket是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值