同源策略、跨域、jsonp

1.什么是同源策略

1.要了解同源策略,我们必须先知道源即orgin

  • 以百度页面为例,谷歌浏览器打开控制台:输入location.origin可得到百度的源
Y`S2F{Q{FHNK0K(FFAL)48V.png
  • 源包括协议版本,域名,端口号。如https://www.baidu.com/,它的协议版本是https,域名为www.baidu,com,默认的端口为443,所以可以省略,类似的还有http协议的默认端口为80,ftp(文本传输协议)的默认端口为21
  • 当知道的源以后,就很容易理解同源策略,即只有源相同(域名、协议、端口相同)的客户端脚本才可以读写对方的资源,反之,不同客户端的脚本不能在没有明确授权的情况下读写对方的资源。举例如下:
  1. 如:http://a.com/a.htmlhttp://b.com/a.html
    二者的域名不相同,不同源,不能读取对方的数据
  2. 如:https://a.com/b.htmlhttp://a.com/b.html
    二者协议版本不一样,不同源,不能读写对方的数据
  3. 如:http://a.com/b.htmlhttp://a.com:80/b.html
    前置省略了默认端口号80,但二者是同源,同时文件路径是否相同和同源无关,所以二者可以读写双方的数据
  • 同源的目的:同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。
    设想这样一种情况:A网站是一家银行,用户登录以后,又去浏览其他网站。如果其他网站可以读取A网站的 Cookie,会发生什么?
    很显然,如果 Cookie 包含隐私(比如存款总额),这些信息就会泄漏。更可怕的是,Cookie 往往用来保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。
    由此可见,"同源政策"是必需的,否则 Cookie 可以共享,互联网就毫无安全可言了。
  • 非同源而限制的三种行为:
  1. Cookie、LocalStorage 和 IndexDB 无法读取
  2. DOM 无法获得。
  3. AJAX 请求不能发送。

2.什么是跨域?跨域有几种实现形式?

  • JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦。这里把涉及到跨域的一些问题简单地整理一下:
    首先什么是跨域,简单地理解就是因为JavaScript同源策略的限制,a.com 域名下的js无法操作b.com或是c.a.com域名下的对象。更详细的说明可以看下表:
1.png
  • 跨域就是利用某种方法来突破同源策略的限制,实现获取对方的资源的目的
  • 跨域的实现方式主要有五种:
  1. 降域:即双方域名不相同,但同时绑定到某个主域名下,通过设置document.domain+iframe。具体的做法是可以在http://www.a.com/a.htmlhttp://script.a.com/b.html两个文件中分别加上document.domain = ‘a.com’;然后通过a.html文件中创建一个iframe,去控制iframe的contentDocument,这样两个js文件之间就可以“交互”了。当然这种办法只能解决主域相同而二级域名不同的情况,
    某一页面的domain默认等于window.location.hostname。主域名是不带www的域名,例如a.com,主域名前面带前缀的通常都为二级域名或多级域名,例如www.a.com其实是二级域名。 domain只能设置为主域名,不可以在b.a.com中将domain设置为c.a.com
  2. JSONP:全称为 JSON with padding ,其实质就是动态的创建script标签来实现跨域,它是基于script可以相互引用,即虽然浏览器默认禁止了跨域访问,但并不禁止在页面中引用其他域的JS文件,并可以自由执行引入的JS文件中的function(包括操作cookie、Dom等等)。根据这一点,可以方便地通过创建script节点的方法来实现完全跨域的通信。
    3.CORS:Cross-origin resource sharing(全称是"跨域资源共享"),它允许它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
  3. 使用HTML5 postMessage:HTML5中最酷的新功能之一就是 跨文档消息传输Cross Document Messaging。下一代浏览器都将支持这个功能:Chrome 2.0+、Internet Explorer 8.0+, Firefox 3.0+, Opera 9.6+, 和 Safari 4.0+ 。 Facebook已经使用了这个功能,用postMessage支持基于web的实时消息传递。
  4. 其他:利用iframe和location.hash和window.name实现的跨域数据传输等

3.jsonp 的原理是什么?

就是利用<script>标签没有跨域限制的“漏洞”(历史遗迹啊)来达到与第三方通讯的目的。当需要通讯时,本站脚本创建一个<script>元素,地址指向第三方的API网址,形如: <script src="http://www.example.net/api?param1=1&param2=2"></script> 并提供一个回调函数来接收数据(函数名可约定,或通过地址参数传递)。 第三方产生的响应为json数据的包装(故称之为jsonp,即json padding),形如: callback({"name":"hax","gender":"Male"})这样浏览器会调用callback函数,并传递解析后json对象作为参数。本站脚本可在callback函数里处理所传入的数据。

  • JSONP的安全隐患
    (1)任意网站只要通过jsonp方式就可以跨域访问目标域名下的信息,解决办法:在跨域请求数据时在参数中加上与目标域名约定好的一个token变量,这样其他网站访问该域名时,目的网站通过辨认这个约定好的信息而决定是否可以被跨域访问。
    (2)不能用post方法获取数据,由于基于src地址引用方式,在地址中附带参数信息,因此只能用get方式获取信息
    (3)callback方法由于是根据用户需求自己实现的,可能会被恶意注入脚本,获取隐私信息。
  • 参考资料:知乎-JSONP 的工作原理是什么?

4.CORS是什么

  1. CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing),CORS定义一种跨域访问的机制,可以让AJAX实现跨域访问。CORS 允许一个域上的网络应用向另一个域提交跨域 AJAX 请求。实现此功能非常简单,只需由服务器发送一个响应标头即可。
  2. CORS 的兼容性,CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
  3. CORS 的请求分为两类:简单请求(simple request)和非简单请求(not-so-simple request)。以简单请求为例
  • 满足以下条件就属于简单请求:
    1.请求方法为:HEAD,GET,POST
    2.HTTP的头部信息为以下字段:
    Accept / Accept-Language / Content-Language / Last-Event-ID/Content-Type(只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain)
  • 凡是不同时满足上面两个条件,就属于非简单请求。
  • 简单请求的基本流程
    1.当你使用 XMLHttpRequest 发送请求时,浏览器发现该请求不符合同源策略,会给该请求加一个请求头: Origin
    2.后台进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头: Access-Control-Allow-Origin ;
  1. 浏览器判断该相应头中是否包含 Origin 的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据
  • 例子:
    假设我们页面或者应用已在 http://www.test1.com 上了,而我们打算从 http://www.test2.com 请求提取数据。一般情况下,如果我们直接使用 AJAX 来请求将会失败。利用 CORS,http://www.test2.com 只需添加一个标头,就可以允许来自 http://www.test1.com 的请求,下图是我在PHP中的 hander() 设置,”号表示允许任何域向我们的服务端提交请求
    header("Access-Control-Allow-Origin:
    "); //*表示允许任何域向我们的服务端提交需求

    header("Access-Control-Allow-Origin:http://www.test1.com") //这样就允许来自http://www.test1.com的需求了
    

通过在HTTP Header中加入扩展字段,服务器在相应网页头部加入字段表示允许访问的domain和HTTP method客户端检查自己的域是否在允许列表中,决定是否处理响应。
服务器端在HTTP的响应头中加入(页面层次的控制模式):
Access-Control-Allow-Origin: example.com
Access-Control-Request-Method: GET, POST
Access-Control-Allow-Headers: Content-Type, Authorization, Accept, Range, Origin
Access-Control-Expose-Headers: Content-Range Access-Control-Max-Age: 3600
多个域名之间用逗号分隔,表示对所示域名提供跨域访问权限。”*”表示允许所有域名的跨域访问。

练习

1.本地搭建服务器,演示同源策略

      一. 本地搭建服务器(如果使用 SAE 可创建不同的代码版本,这样可通过      
      1.xxx.sinapp.com和2.xxx.sinapp.com 访问了)
      2. 修改 本地host,通过不同域名访问本地服务器。比如访问http://a.com/index.html, http://b.com/ajax.php,本质是
      3. 在 index.html 里使用 ajax 接口访问 http://b.com/ajax.php 里的数据。
      4. 查看输出报错
  • 卡在这一关很久了,因为一直不懂,现在又点懂了,老师视频上用的node.js不会,所用用了本地PHP软件测试
  • 1.第一步,打开host 文件,直接可在 win+r 在运行了,输入它的地址 Windows/System32/drivers/etc ,即可找到,如图;

![FUD_4]4@(373R({WX}6AM2G.png](http://upload-images.jianshu.io/upload_images/3361706-0ed330d1d707587b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

  • 2.直接用编辑器或记事本打开即可,若是发现host里面是空白,那是因为杀毒软件360,qq管家刚刚修复过,所以是空的,里面加上这段代码就行了

      # Copyright (c) 1993-1999 Microsoft Corp.
      #
      # This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
      #
      # This file contains the mappings of IP addresses to host names. Each
      # entry should be kept on an individual line. The IP address should
      # be placed in the first column followed by the corresponding host name.
      # The IP address and the host name should be separated by at least one
      # space.
      #
      # Additionally, comments (such as these) may be inserted on individual
      # lines or following the machine name denoted by a '#' symbol.
      #
      # For example:
      #
      #      102.54.94.97           rhino.acme.com          # source server
      #       38.25.63.10     x.acme.com              # x client host
    
  • 第三步,给本地默认IP 127.0.0.1 绑定 两个域名,用于测试


    1.png.png
  • 第四步,在www.a.com/index.html ,通过ajax给www.b.com/test-1.php 发送请求
    以下是index.html 的代码

        <!DOCTYPE html>
      <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>index</title>
    </head>
    <body>
      <script src="http://apps.bdimg.com/libs/jquery/1.9.1/jquery.js"></script>
      <script type="text/javascript">
      $.ajax({
          url:'http://www.b.wang.com/test-1.php',
          type:'get',
          dataType:'json',
          data:{
              username:'xiaoming',
              sex:'man'
          },
          success:function(data){
              alert(data)
          },
          error:function(){
              alert('出错')
          }
      })
    </script>
      </body>
    </html>
    

以下是 www.b.wang.com的test-1.php的代码
<?php
$data='获取数据成功';
echo json_encode($data);
?>

  • 第五步,查看结果,分析原因,如图:


    2.png

    ajax请求发送失败,查看控制台显示:


    F}C[HBV8QG(OGH{N]DVBO8C.png

2.解决同源策略的限制

1.CORS,未来跨域方法的趋势,使用ajax十分简单,安全性高,但是兼容不好,至少要IE10以上,但是随着时代进步,早晚是CORS的天下。

  • 具体方式:在www.b.wang.com/test-1.php中添header("Access-Control-Allow-Origin: http://www.a.wang.com");
    即允许来自源www.a.wang.com的请求;

    <?php 
      header("Access-Control-Allow-    Origin: http://www.a.wang.com");
      $data='获取数据成功';
      echo json_encode($data);
     ?>
    
  • 结果成功的获取到www.b.wang.com下的test-1.php的数据,如图:

{~O$$3}E(`F}1IIYV{SZ}@I.png
  1. jsonp,利用动态的script便签的创建获取到数据
    index.html的代码如下:
    <script type="text/javascript">
    function jsonp(data){
    alert(data)
    }
    var script=document.createElement('script');
    script.src='http://www.b.wang.com/test-1.php?callback=abc';
    document.body.insertBefore(script,document.body.firstChild);

     </script>
    

test-1.php 代码如下:
jsonp('123456789');

  • 结果如图:成功获取到了数据:
E`RS(0E4)4E2YOUEDXRJ)4Y.png

版权和饥人谷和作者所有,若需转载请注明出处

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

推荐阅读更多精彩内容