zoukankan      html  css  js  c++  java
  • 同源策略和跨域解决方法

    第一部分:同源策略:same-origin policy

    1.同源策略的由来:

    1995年,同源策略由Netscape(曾经的浏览器霸主,拒绝微软收购请求,被IE给整垮。现在发展为火狐浏览器背后的Mozilla)引入。目前,所有浏览器都遵循同源策略

    2.同源定义:即同协议、同域名、同端口号

    例如:http://www.test.com:80/test.html;     协议:http;域名:www.test.com;端口号:80(默认端口,可以省略)

    http://www.test.com/test100.html    (同源)
    http://test.com/test100.html      (不同源,域名不同)
    http://x.www.test.com/test100.html  (不同源,域名不同)
    http://www.test.com:81/test100.html  (不同源,端口号不同)
    https://www.test.com/test100.html  (不同源,协议不同)

    但是在IE浏览器上端口号不同被认为是同源

    截图自MDN,链接

     

    3.同源策略目的:

    防止其它网站恶意窃取数据。
    例如: 假设没有同源策略:用户在银行网站A上访问,cookie记录了A银行存款金额、存款频率、存款频率等信息;当用户离开A网站,访问游戏网站B时,此时网站B可以读取cookie。那么用户的隐私就被泄露了!
    更严重的是,cookie往往保存用户登录状态,如果用户离开A网站(但是没有退出登录),那么B网站其实是可以冒充用户进入A网站

    4.非同源带来的结果:

    • cookie,localStorage和indexdDB无法读取
    • DOM无法获得
    • Ajax请求无效(请求发送后,浏览器不会进行响应)

    第二部分:跨域解决方法

    1.设置document.domain来跨子域:(适用于cookie、iframe)

    比如http://a.test.com和http://b.test.com;

    如果设置了document.domain='test.com';那么两者之间可以共享cookie(即一级域名相同,二级域名不同,可以设置document.domain来共享cookie)

    同时,服务器可以在设置cookie的时候,指定一级域名,也能达到共享cookie的效果。如:Set-Cookie:key=value;domain=.test.com;path=/

    iframe:也可以通过上述document.cookie设置,从而共享cookie、iframe拿到父窗口的DOM、父窗口拿到iframe的DOM。

    如:父窗口是http://a.test.com,iframe是http://test.com;当设置了document.domain="test.com"时,就能进行跨域了。

    2.同源域名下架设代理服务器:JavaScript将请求发送到代理服务器,代理服务器再将结果返回。

    如:'/proxy?url=http://www.test.com'

    不过这种显然需要配置额外服务器,开销变大。

    3.使用window.name来跨域:

    window.name:在不同的页面(甚至不同的域名)加载后依然存在(如果值没被修改,则不会发生变化),并且name值可达2MB(对于一般的运用完全够用)

    4.片段识别符(fragment identifier)URL中#后面的部分。比如http://www.test.com#apple的#apple就是片段识别符。

    改变片段识别符,页面不会重新刷新

    父窗口将信息,写入子窗口片段识别符;子窗口通过监听hashchange事件得到通知

    5.window.postMessage:HTML5为了解决跨域问题,引进的全新API:跨文档通信API(cross-document messaging)

    父窗口:http://a.com,子窗口:http://b.com;显然两者不同源,但是通过postMessage两者可以实现跨域通信

     1 var a=window.open('http://b.com');
     2         //父窗口向子窗口发送信息hello 1
     3         a.postMessage('hello 1','http://b.com');
     4         //子窗口向父窗口发送信息hello 2
     5         window.opener.postMessage('hello 2','http://a.com');
     6 
     7         //父窗口和子窗口都能通过message事件,监听对方信息
     8         window.addEventListener('message',function(e){
     9             console.log(e.data);
    10         })

    6.JSONP:这个就很常见了。老式浏览器都支持,兼容性好,简单实用。(不过只支持get请求)

    基本思想:网页通过添加一个<script>元素,向服务器发送JSON数据,这种方法是不受同源策略限制的;服务器收到请求后,将数据放入指定的回调函数中返回。

    截图至阮一峰JavaScript标准参考教程。

    添加<script>元素,向服务器发送请求,同时请求中指明了回调函数foo,服务器以回调函数的形式返回数据。

    7.websocket:这个是通信协议,好比是打电话。与传统的http协议,只能客户端向服务器发送请求,服务器进行效应的原理不同。

    websocket可以由客户端向服务器发送连接请求,也可以服务器向客户端发送连接请求。它们之间的连接是持续打开的数据通道,就好比是打电话!

    websocket不受同源策略制约,可以用来跨域通信。将可以通信的域名放在白名单里。

    8.安装flash插件,现在flash插件用的越来越少,而且复杂。不推荐!

    9.CORS(跨域资源共享)cross-origin resource sharing支持所有类型的请求,对比JSONP只支持get请求

    它是一个W3C标准,允许浏览器跨域发送XMLHttpResuest对象。这是Ajax跨域的终极解决方法。

    目前,IE10以上,现代浏览器均支持CORS。

    主要原理:浏览器发现Ajax跨域请求,就会自动添加一些头部信息;对于非简单请求,还会多出一次附加请求;但是这些用户都察觉不到。而服务器端布置了CORS接口(设置了相关数据信息如:Access-Control-Allow-Origin)

    所以:CORS需要客户端与服务器同时支持!

    更多详细参考:阮一峰JavaScript标准参考教程

    10.可参见:PHP Ajax 跨域问题最佳解决方案

    通过设置Access-Control-Allow-Origin来实现跨域。

    更多参考:1.阮一峰JavaScript标准参考教程

    2.Ajax廖雪峰的官方网站

    3.js中几种常见的跨域方法原理详解

  • 相关阅读:
    深入理解C++ 11新特性:1)
    Effective Java 第三版:1)
    Java 8 实战:2)
    MyBatis Plus
    Java 8 实战:1)
    十二要素应用宣言
    Dubbo 2):源码级
    [SCOI2009]windy数 数位dp
    [ZJOI2006]物流运输 最短路 动态规划
    [ZJOI2008]骑士
  • 原文地址:https://www.cnblogs.com/why-not-try/p/8038360.html
Copyright © 2011-2022 走看看