美文网首页
浏览器的同源策略

浏览器的同源策略

作者: 李华炎 | 来源:发表于2018-04-07 20:55 被阅读0次

    浏览器的同源策略

    浏览器安全的基石是"同源政策"(same-origin policy

    一、概述

    A网页设置的 Cookie,B网页不能打开,除非这两个网页"同源"。所谓"同源"指的是"三个相同"。

    • 协议相同
    • 域名相同
    • 端口相同(默认的端口是80)

    举例来说,http://www.example.com/dir/page.html这个网址,协议是http://,域名是www.example.com,端口是80(默认端口可以省略)。它的同源情况如下。

    http://www.example.com/dir2/other.html          //同源
    http://example.com/dir/other.html               //不同源(域名不同)
    http://v2.www.example.com/dir/other.html        //不同源(域名不同)
    http://www.example.com:81/dir/other.html        //不同源(端口不同)
    
    // 注意:
    // 浏览器同时还规定,提交表单不受同源政策的限制。
    
    1级域名.png

    二、非同源的限制

    随着互联网的发展,"同源政策"越来越严格。目前,如果非同源,共有三种行为受到限制。

    1. Cookie、LocalStorage 和 IndexDB 无法读取。
    2. DOM 无法获得(浏览器不允许从一个document中访问另一不同域下的document的dom元素)
    3. AJAX 请求不能发送(不能向非同源的网站获取数据)

    三、Ajax

    同源政策规定,AJAX请求只能发给同源的网址,否则就报错。

    除了架设服务器代理(浏览器请求同源服务器,再由后者请求外部服务),有三种方法规避这个限制。

    1. JSONP
    2. WebSocket
    3. CORS

    1. JSONP

    JSONP是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,老式浏览器全部支持,服务器改造非常小。

    它的基本思想是,网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。

    首先,网页动态插入<script>元素,由它向跨源网址发出请求。

    function addScriptTag(src) {
      var script = document.createElement('script');
      script.setAttribute("type","text/javascript");
      script.src = src;
      document.body.appendChild(script);
    }
    
    window.onload = function () {
      addScriptTag('http://example.com/ip?callback=foo');
    }
    
    function foo(data) {
      console.log('Your public IP address is: ' + data.ip);
    };
    

    上面代码通过动态添加<script>元素,向服务器example.com发出请求。注意,该请求的查询字符串有一个callback参数,用来指定回调函数的名字,这对于JSONP是必需的。

    服务器收到这个请求以后,会将数据放在回调函数的参数位置返回。

    foo({
      "ip": "8.8.8.8"
    });
    

    由于<script>元素请求的脚本,直接作为代码运行。这时,只要浏览器定义了foo函数,该函数就会立即调用。作为参数的JSON数据被视为JavaScript对象,而不是字符串,因此避免了使用JSON.parse的步骤。

    2.webSocket

    WebSocket是一种通信协议,使用ws://(非加密)和wss://(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。

    下面是一个例子,浏览器发出的WebSocket请求的头信息(摘自维基百科)。

    GET /chat HTTP/1.1
    Host: server.example.com
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
    Sec-WebSocket-Protocol: chat, superchat
    Sec-WebSocket-Version: 13
    Origin: http://example.com
    

    上面代码中,有一个字段是Origin,表示该请求的请求源(origin),即发自哪个域名。

    正是因为有了Origin这个字段,所以WebSocket才没有实行同源政策。因为服务器可以根据这个字段,判断是否许可本次通信。如果该域名在白名单内,服务器就会做出如下回应。

    HTTP/1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
    Sec-WebSocket-Protocol: chat
    

    3.CORS

    CORS是跨源资源分享(Cross-Origin Resource Sharing)的缩写。它是W3C标准,是跨源AJAX请求的根本解决方法。相比JSONP只能发GET请求,CORS允许任何类型的请求。

    相关文章

      网友评论

          本文标题:浏览器的同源策略

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