• 跨域通信


    在工作的一段时间里,给我最大的感触就是:公司有非常多的子系统,而且子系统与子系统之间交互非常的频繁,虽然公司拥有封装了HttpClient及增加了路由功能的R系统(该系统目的就是满足现下系统与系统之间通信频繁的问题),但是大家都知道HttpClient只限于服务器端使用,当我们想用客户端脚本,比如Javascript来调用其他系统(不同域)的接口时,就会出现跨域通信的问题。那么为什么会出现跨域通信问题呢?当遇到跨域通信问题时,我们又有几种解决方案呢?另外,跨域通信又会引发哪些潜在的问题呢?下面我将慢慢解释这几个问题。

    一、产生跨域通信问题的本质原因

      "无规矩不成方圆",这句话大家都知道,当我们在互联网的浪潮中冲浪的时候,我们无需考虑任何安全问题。因为互联网为了网民的安全,定制了很多策略(规矩),有一种策略叫同源策略,是每一种浏览器都必须实现并遵守的!那么同源策略到底限制了什么呢?

      同源策略规定:不同客户端脚本在没有明确授权的情况下,不能读写对方的资源(好比你不能碰别人的女朋友一样),这里有几个关键字很有必要解释一下。

      1、域、子域、同域

          所谓同域(源)指:当A域与B域具有相同的协议、域名、端口时称为同域(源)

      2、客户端脚本:由浏览器解释和执行的脚本语言,比如现下流行的Javascript,ActionScript,之前流行的VBScript   

      3、授权:服务端可以对客户端的访问进行授权,那么客户端也可以授权,比如HTML5中新标准中,当目标站点返回HTTP响应头Access-Control-Allow-Origin:http://www.cnblogs.com(A),那么浏览器就允许A站点去访问目标站点。   

      4、读写权限:Web上的资源很多,比如HTTP请求头的Referer只读,cookie即可写亦可读

      5、资源:资源是个广泛的概念,只要是数据都可以认为是资源。同源策略里的资源特指Web客户端的资源(HTTP头,DOM树..)

    在这里特别要注意的是,同源策略虽然限制了客户端的资源,但对静态的资源文件是没有加以限制的,例如客户端脚本文件,样式CSS文件、图片,flash资源等静态文件。(<script src=""><img src=""> <link rel=""><iframe src="">),但如果A域的js,想修改B域的dom元素也会造成跨域问题(2014.4.28补充)

    二、为什么需要同源策略限制

       我们举例说明:比如一个黑客程序,他利用iframe把真正的银行登录页面嵌到他的页面上,当你使用真实的用户名,密码登录时,他的页面就可以通过Javascript读取到你的表单中input中的内容,这样用户名,密码就轻松到手了。如果没有该策略的限制,后果可想而知。

    三、同源策略的应用场景

    前面介绍了同源策略的规定其存在的价值,那么浏览器的同源策略究竟在哪些场景会起作用呢?下面的三种场景是比较常见的!

      1、窗口与窗口(不同域)之间的交互

      2、iframe嵌入了不同域的资源(浏览器并不限制iframe嵌入不同域的资源,但限制客户端脚本去访问)

      3、AJax应用(异步),请求不同域的资源

    四、绕过同源策略解决跨域通信的方式

      互联网的发展催生了跨域通信的需求,各种跨域方法和协议满足了需求但也增加了各种风险(风险下面会讲)。尤其是现在mashup的盛行。那么怎么去绕过浏览器的同源策略呢?下面我会讲在实际应用中比较常用的绕过同源策略的方式,这些方式会分为:客户端技术和服务端技术。但这两种方式的本质就是利用同源策略的一个漏洞(同源策略虽然限制了客户端的资源,但对静态的资源文件是没有加以限制的)和浏览器中不能直接来跨域访问,而在服务器端没有跨域安全限制(可以在服务端完成跨域访问,而在客户端来取得结果)。客户端技术利用的是前者,而服务端技术利用的是后者。

      客户端技术

    1. iframe + document.domain(仅适用于子域之间,例如bbs.pclady.com.cn和www.pclady.com.cn) 
    2. iframe(其原理:在iframe加载新页面时,window.name的值是保持不变的,由此可以重定向iframe的引用地址,由外域转到本域) -> JQuery的window.name插件(封装了iframe的实现) -- 支持post请求
    3. 动态Script标签->Jsonp -> JQuery的$.getScript(弊端只支持get请求,没有差错控制机制)
    4. HTML5 postMessage(需要现代的浏览器才兼容,像之前的ie6不兼容)
    5. Flash + crossdomain跨域(需要用户安装flash,在互联网应用里用户体验不好)

    1、动态Script标签,返回的数据格式必须是text/javascript(并非一定是JSON,可以是任何数据类型),跨域通信盛行之后,慢慢就产生了JSONP的概念(就是将动态插入Script标签的技术美称为JSONP,但网上却有一大堆关于JSONP的解释,简直是误导众生啊!)

     1 <html> 
     2 <head> 
     3 <title>How Many Pictures Of Madonna Do We Have?</title> 
     4 <script type="text/javascript"> 
     5 // 回调函数
     6 function ws_results(obj) 
     7 { 
     8     // obj的格式可以是任意数据类型,比如JSON,字符串,xml
     9     // 我们只需要相应的解析即可
    10     // 服务器端的返回格式一定得是这样  ws_results(obj);
    11     alert(obj.ResultSet.totalResultsAvailable); 
    12 } 
    13  
    14 function onClick() 
    15 { 
    16     var script = document.createElement("script"); 
    17     script.type = "text/javascript"; 
    18     script.src = "http://search.yahooapis.com/ImageSearchService/V1/imageSearch?appid=YahooDemo&query=Madonna&output=json&callback=ws_results"; 
    19     document.body.appendChild(script); 
    20 } 
    21 </script> 
    22 </head> 
    23 <body> 
    24 <input type="button" value="click me!" onclick="onClick()"> 
    25 </body> 
    26 </html>
    View Code

    2、Iframe+document.domain

     1 /*
     2     对于主域相同而子域不同的例子,可以通过设置document.domain的办法来解决。具体的做法是可以在http://www.a.com/a.html和http://script.a.com/b.html两个文件中分别加上document.domain = ‘a.com’;然后通过a.html文件中创建一个iframe,去控制iframe的contentDocument,这样两个js文件之间就可以“交互”了。当然这种办法只能解决主域相同而二级域名不同的情况,如果你异想天开的把script.a.com的domian设为alibaba.com那显然是会报错地!
     3 */代码如下:
     4 www.a.com上的a.html
     5 document.domain = 'a.com';
     6 var ifr = document.createElement('iframe');
     7 ifr.src = 'http://script.a.com/b.html';
     8 ifr.style.display = 'none';
     9 document.body.appendChild(ifr);
    10 ifr.onload = function(){
    11     var doc = ifr.contentDocument || ifr.contentWindow.document;
    12     // 在这里操纵b.html
    13     alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue);
    14 };
    15 
    16 script.a.com上的b.html
    17 document.domain = 'a.com';
    18 /*
    19 这种方式适用于{www.kuqin.com, kuqin.com, script.kuqin.com, css.kuqin.com}中的任何页面相互通信。
    20 备注:某一页面的domain默认等于window.location.hostname。主域名是不带www的域名,例如a.com,主域名前面带前缀的通常都为二级域名或多级域名,例如www.a.com其实是二级域名。 domain只能设置为主域名,不可以在b.a.com中将domain设置为c.a.com。
    21 这种方式的缺陷:
    22 1、安全性,当一个站点(b.a.com)被攻击后,另一个站点(c.a.com)会引起安全漏洞。
    23 2、如果一个页面中引入多个iframe,要想能够操作所有iframe,必须都得设置相同domain。
    24 */
    View Code

    3、Iframe->window.name 详情可查看http://www.cnblogs.com/rainman/archive/2011/02/21/1960044.html

     1 <html>
     2 <head>
     3 <title>ddd</title>
     4 </head>
     5 <body>
     6 <script type="text/javascript">
     7 function check()
     8 {
     9     var btn = document.getElementById("test_submit");
    10     var frm = document.forms["test_form"];
    11     var ifm = document.getElementById("test_iframe");
    12     frm.action = "http://xxx.xxx.xxx/post.php";
    13     frm.target = "test_iframe";
    14     frm.submit();
    15     btn.disabled = "disabled";
    16     ifm.onload = function(){
    17         btn.disabled = "";
    18         var str = ifm.contentWindow;
    19         alert(str.document.body.innerHTML);
    20         ifm.src = "about:blank"; 
    21         ifm.onload = null; 
    22     }     
    23     return false; 
    24 
    25 }
    26 
    27 </script>
    28 <form id="test_form" name="test_form" >
    29     <input type="hidden" name="content" value="xxx" />
    30     <input type="submit" name="test_submit" id="test_submit" />
    31 </form>
    32 <iframe id="test_iframe" name="test_iframe" width="1" height="1" style="display:none"></iframe>
    33 </body>
    34 </html>
    35 
    36 Iframe实现post跨域
    Iframe实现post跨域

    4、5由于用得不多,在这里就不详细解释了!详细可查看http://book.51cto.com/art/200903/113178.htm

      服务端技术

    1. 正向代理:与浏览器原理一样
    2. 反向代理:利用apache server或者nginx等Http服务器进行对url进行重写
    3. HttpClient: 模拟Http请求(通过HttpClient对其它域发出HTTP请求,只要不通过浏览器就不会有同源策略的限制)

    在那么多处理方式中,当然每种方式都有它们的优缺点,当我们去选择这些方式的时候,我们应该以下面几个方面去考虑。

      1、自己是否可以操作其它域的服务端的资源

      2、请求的方式是get还是post

      3、跨域通信的方式(跨域通信有2种:本域和子域通信本域和其它域通信)

    五、绕过同源策略引发的问题

      在避免同源策略时会向恶意用户露出攻击面,当恶意代码被插入 Web 应用程序中时当前的应用程序也易于受到攻击。遗憾的是,恶意代码进入 Web 应用程序的方法多种多样。使我们防不胜防。两种比较常见的的XSS(反射式与存储式)和CSRF,有兴趣的可以具体去了解一下!

    六、其它同源策略

       Cookie 同源策略:Cookie中的同源只关注域名,忽略协议和端口。所以https://localhost:8080/和http://localhost:8081/的Cookie是共享的。

  • 相关阅读:
    caffe 学习(1) —— Classification: Instant Recognition with Caffe
    Latex 编辑器安装
    Ubuntu 14.04上安装caffe
    学习换脸:Switching Eds: Face swapping with Python, dlib, and OpenCV
    如何给磁盘文件排序?--学习《编程珠玑》
    android五种数据存储方式
    PAML学习一
    Google TensorFlow 学习笔记一 —— TensorFlow简介
    mfc学习笔记
    新建标准库
  • 原文地址:https://www.cnblogs.com/lijianwen/p/3471790.html
Copyright © 2020-2023  润新知