同源策略、跨域、jsonp

作者: GarenWang | 来源:发表于2016-12-13 14:24 被阅读558次

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:https://img.haomeiwen.com/i3361706/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

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

相关文章

  • 前端基础(问答23)

    keywords: 同源策略、跨域、jsonp。 什么是同源策略(same origin policy) 同源:协...

  • 跨域

    主要内容: 同源策略、跨域实现形式(JSONP、CORS、降域、postMessage) 同源策略 (Same o...

  • 做demo和学习过程当中遇到的一些问题,收集的博文

    轻松搞定JSONP跨域请求--->关键字: 跨域, 同源策略, JSONP原理 git拉取远程分支到本地 git ...

  • jsonp

    jsonp的跨域原理解析 背景: 由于浏览器同源策略的限制,非同源下的请求,都会产生跨域问题,jsonp就是为了解...

  • Jsonp 跨域原理

    Jsonp 跨域原理。(摘选) 浏览器的同源策略把跨域请求都禁止了,但是页面中的 标签是例外,不受同源策略限...

  • 什么是跨域

    被同源策略限制的都叫做跨域,域名,端口,协议一只就要同源策略 如果跨域 1、jsonp 2、nginx反向代理 3...

  • 同源策略与跨域

    跨域就是违背了同源策略解决跨域的方法有:jsonp,cors和服务器代理

  • 常见跨域解决方案

    跨域 JSONP 使用 标签不受同源策略影响的特性,作为Ajax传输技术称为JSONP。 使用JSONP时,需要服...

  • Jsonp的实现原理

    1. Jsonp Jsonp: 主要是用来获取跨域的请求,由于同源策略的限制,我们不能获取跨域的资源 2. Jso...

  • Ajax跨域 —— Jsonp

    同源策略 同源/同域即域名、协议、端口号相同 JSONP(JSON with Padding) 是一种跨域请求方式...

网友评论

本文标题:同源策略、跨域、jsonp

本文链接:https://www.haomeiwen.com/subject/gnlpmttx.html