同源策略、跨域、jsonp

发布时间:2016-12-22 17:08 阅读:39

文/饥人谷 任务9班_王晓雨

本文著作权归作者所有;如需转载请联系饥人谷,并注明原文出处

1.什么是同源策略

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

  • 以百度页面为例,谷歌浏览器打开控制台:输入location.origin可得到百度的源

  • 源包括协议版本,域名,端口号。如https://www.baidu.com/,它的协议版本是https,域名为www.baidu,com,默认的端口为443,所以可以省略,类似的还有http协议的默认端口为80,ftp(文本传输协议)的默认端口为21
  • 当知道的源以后,就很容易理解同源策略,即只有源相同(域名、协议、端口相同)的客户端脚本才可以读写对方的资源,反之,不同客户端的脚本不能在没有明确授权的情况下读写对方的资源。举例如下:
  • 如:http://a.com/a.htmlhttp://b.com/a.html

    二者的域名不相同,不同源,不能读取对方的数据
  • 如:https://a.com/b.htmlhttp://a.com/b.html

    二者协议版本不一样,不同源,不能读写对方的数据
  • 如:http://a.com/b.htmlhttp://a.com:80/b.html

    前置省略了默认端口号80,但二者是同源,同时文件路径是否相同和同源无关,所以二者可以读写双方的数据
  • 同源的目的:同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。 设想这样一种情况:A网站是一家银行,用户登录以后,又去浏览其他网站。如果其他网站可以读取A网站的 Cookie,会发生什么? 很显然,如果 Cookie 包含隐私(比如存款总额),这些信息就会泄漏。更可怕的是,Cookie 往往用来保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。 由此可见,"同源政策"是必需的,否则 Cookie 可以共享,互联网就毫无安全可言了。
  • 非同源而限制的三种行为:
  • Cookie、LocalStorage 和 IndexDB 无法读取
  • DOM 无法获得。
  • AJAX 请求不能发送。
  • 参考资料:阮一峰的网络日志 -浏览器同源政策

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

  • JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦。这里把涉及到跨域的一些问题简单地整理一下: 首先什么是跨域,简单地理解就是因为JavaScript同源策略的限制,a.com 域名下的js无法操作b.com或是c.a.com域名下的对象。更详细的说明可以看下表:

  • 跨域就是利用某种方法来突破同源策略的限制,实现获取对方的资源的目的
  • 跨域的实现方式主要有五种:
  • 降域:即双方域名不相同,但同时绑定到某个主域名下,通过设置document.domain+iframe。具体的做法是可以在http://www.a.com/a.html和http://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。
  • JSONP:全称为 JSON with padding ,其实质就是动态的创建script标签来实现跨域,它是基于script可以相互引用,即虽然浏览器默认禁止了跨域访问,但并不禁止在页面中引用其他域的JS文件,并可以自由执行引入的JS文件中的function(包括操作cookie、Dom等等)。根据这一点,可以方便地通过创建script节点的方法来实现完全跨域的通信。 3.CORS:Cross-origin resource sharing(全称是"跨域资源共享"),它允许它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
  • 使用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的实时消息传递。
  • 其他:利用iframe和location.hash和window.name实现的跨域数据传输等
  • 参考资料:JavaScript跨域总结与解决办法

3.jsonp 的原理是什么?

就是利用标签没有跨域限制的“漏洞”(历史遗迹啊)来达到与第三方通讯的目的。当需要通讯时,本站脚本创建一个元素,地址指向第三方的API网址,形如: ` 并提供一个回调函数来接收数据(函数名可约定,或通过地址参数传递)。 第三方产生的响应为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 ;
    • 浏览器判断该相应头中是否包含 Origin 的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据
  4. 例子: 假设我们页面或者应用已在 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 ,即可找到,如图;

  • 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 绑定 两个域名,用于测试

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

    
    index
    
      $.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('出错')
          }
      })
    

    以下是 www.b.wang.com的test-1.php的代码

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

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

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的请求;

  • 结果成功的获取到www.b.wang.com下的test-1.php的数据,如图:

  1. jsonp,利用动态的script便签的创建获取到数据 index.html的代码如下:

    
     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);
    

    test-1.php 代码如下:

    jsonp('123456789');
  2. 结果如图:成功获取到了数据:

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

可以输入140个字