zoukankan      html  css  js  c++  java
  • 程序员应对浏览器同源策略的姿势

    同源策略

      浏览器最基本的安全规范——同源策略(Same-Origin Policy)。所谓同源是指,域名,协议,端口相同。不同源的浏览器脚本(javascript、ActionScript、canvas)在没明确授权的情况下,不能读写对方的资源

      同源策略规定了 浏览器脚本互操作web数据的基本原则。

    若没有这一基本原则,那么:

            ① 某域下DOM元素被另一方任意操作、篡改, 导致页面显示失控

            ② 某域下的Cookie等与该域相关的密切数据可以任意读取,导致与该域密切相关的浏览器cookie片段可能失真

            ③ 恶意网站能随意执行Ajax脚本偷取隐私数据,导致该域下核心业务数据被抓取。

    同源策略在实施中面临的问题

           默认的同源策略 限制了脚本互操作其他域的能力,大棒一挥, 关闭了A站脚本正常访问B站数据的需求

    所以有以下变通方法:

    ① 实现CORS (Cross-Origin Resource Sharing) : 

    ② 使用JSONP (JSON Padding)

    ③ 建立一个本地代理服务器,这样先同源访问,由代理服务器转发请求

    以上①CORS是w3C 对于跨域请求推出的明确方案;②③方式都是一种Hack行为。

    CORS跨域请求方案

    W3C推出的跨域请求方案: 让web服务器明确授权 非同源页面脚本来访问自己, 以Response 特定标头 Access-Control-****-****  体现;   目前现代浏览器均认可并支持这些标头。

    CORS新HTTP标头,为浏览器提供了在获得许授权,脚本才能访问其他域名页面数据的通道。

    常规的携带Cookie Ajax跨域Get请求

    const invocation = new XMLHttpRequest();
    const url = 'http://bar.other/resources/credentialed-content/';
        
    function callOtherDomain(){
      if(invocation) {
        invocation.open('GET', url, true);
        invocation.withCredentials = true;   // Ajax请求默认不会发送凭据, 这里设定在Ajax跨域请求中发送凭据
        invocation.onreadystatechange = handler;
        invocation.send(); 
      }
    }

    CORS规范

             ① 浏览器发起CORS或POST请求,浏览器会自动携带Origin标头(指示请求来自于哪个站点)

             ② Web服务器实现跨站访问授权逻辑, 授权结果在Response中以 Access-Control--******* 标头体现

    最常见的Access-Control-Allow-Origin标头包含  * / Origin /null  三种响应值;

    当请求是携带凭据的跨域请求,不可囫囵吞枣地指定为*通配符,而必须指定特定Origin

             ③ 浏览器会遵守Access-Control--*******-- 标头值所施加的跨域限制

    GET /resources/access-control-with-credentials/ HTTP/1.1
    Host: bar.other
    User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Connection: keep-alive
    Referer: http://foo.example/examples/credential.html
    Origin: http://foo.example
    Cookie: pageAccess=2
    
    
    HTTP/1.1 200 OK
    Date: Mon, 01 Dec 2008 01:34:52 GMT
    Server: Apache/2.0.61 (Unix) PHP/4.4.7 mod_ssl/2.0.61 OpenSSL/0.9.7e mod_fastcgi/2.4.2 DAV/2 SVN/1.4.2
    X-Powered-By: PHP/5.2.6
    Access-Control-Allow-Origin: http://foo.example
    Access-Control-Allow-Credentials: true
    Cache-Control: no-cache
    Pragma: no-cache
    Set-Cookie: pageAccess=3; expires=Wed, 31-Dec-2008 01:34:53 GMT
    Vary: Accept-Encoding, Origin
    Content-Encoding: gzip
    Content-Length: 106
    Keep-Alive: timeout=2, max=100
    Connection: Keep-Alive
    Content-Type: text/plain
    
    
    [text/plain payload]

     以上表示了一个常见的携带Cookie跨域Ajax Get请求, 其中 Access-Control-Allow-Credentials: true 指令浏览器可以将跨域请求的 Response 结果暴露给页面。

    预检Preflight

            对于非简单Ajax请求(通常是GET以外的HTTP方法,或者某些MIME类型的POST用法),CORS规范要求发起 "预检" 请求。

     不过,这个请求不需要你手动发起,浏览器会自动使用OPTIONS请求方法从服务器请求支持的方法,然后,在服务器“批准”时,使用实际的HTTP请求方法发送实际请求。

    下图显示 浏览器判断 非简单请求的逻辑图:

    下面使用POST动作发起Ajax跨域请求,同时自定义了一个request header: X-PINGOTHER, 该请求触发浏览器预检行为

    const invocation = new XMLHttpRequest();
    const url = 'http://bar.other/resources/post-here/';
    const body = '<?xml version="1.0"?><person><name>Arun</name></person>';
        
    function callOtherDomain(){
      if(invocation)
        {
          invocation.open('POST', url, true);
          invocation.setRequestHeader('X-PINGOTHER', 'pingpong');
          invocation.setRequestHeader('Content-Type', 'application/xml');
          invocation.onreadystatechange = handler;
          invocation.send(body); 
        }
    }

    程序员调试CORS的苦恼

    跨域请求发生在A--->B 两站,作为某一方开发人员,调试CORS相对麻烦。

    经过本StackOverFlow工程师的检索,curl 工具可优雅高效模仿Ajax跨域请求:

    #  http://example.com 向谷歌站点发起一个跨域Get请求

    curl -H "Origin: http://example.com" --verbose https://www.googleapis.com/discovery/v1/apis?fields=

     从浏览器Network,将请求格式 以cUrl形式拷贝出来,改改。

    总结

      ①  浏览器同源策略 作用对象是 浏览器脚本;

      ②  存在跨域请求的场景,某些方案是Hack行为;

      ③  W3C推出的CORS 是标准的跨域请求方案,思路是 在服务端Response标头体现 授权, 浏览器遵守该授权标头。

      ④  对于非简单的脚本跨域请求,浏览器会自动发起 Option请求预检, 大部分时候无需关注

      ⑤ 提供curl 工具帮助高效、优雅调试CORS。

    后面会介绍浏览器的另一个有用的安全策略: Cookie SameSite策略。

    https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

    https://stackoverflow.com/questions/12173990/how-can-you-debug-a-cors-request-with-curl/12179364#12179364

    https://curl.haxx.se/docs/manpage.html

  • 相关阅读:
    PAT 1063 计算谱半径(20)(代码)
    PAT 1071 小赌怡情(15)(代码)
    PAT 1068 万绿丛中一点红(20)(测试点分析+思路分析)
    PAT 甲级 1011 World Cup Betting (20)(代码+思路)
    PAT 1041 考试座位号(15)(代码)
    PAT 1076 Wifi密码(15)(代码)
    Mvc全局过滤器与Action排除
    .NET Core WebApi使用Swagger
    .NET WebApi使用Swagger
    JQuery常见方法
  • 原文地址:https://www.cnblogs.com/JulianHuang/p/10337980.html
Copyright © 2011-2022 走看看