zoukankan      html  css  js  c++  java
  • 跨域

    浏览器安全

    浏览器安全可以分为三大块--Web页面安全、浏览器网络安全和浏览器系统安全

    本次主要介绍分析页面中的安全策略。在开始之前,我们先来做个假设,如果页面中没有安全策略的话,Web世界会是什么样的呢?

    • Web 世界会是开放的,任何资源都可以接入其中,我们的网站可以加载并执行别人网站的脚本文件、图片、音频 / 视频等资源,甚至可以下载其他站点的可执行文件。
    • Web 世界是开放的,这很符合 Web 理念。但如果 Web 世界是绝对自由的,那么页面行为将没有任何限制,这会造成无序或者混沌的局面,出现很多不可控的问题。

    比如你打开了一个银行站点,然后又一不小心打开了一个恶意站点,如果没有安全措施,恶意站点就可以做很多事情:

    • 修改银行站点的 DOM、CSSOM 等信息;
    • 在银行站点内部插入 JavaScript 脚本;
    • 劫持用户登录的用户名和密码;
    • 读取银行站点的 Cookie、IndexDB 等数据;
    • 甚至还可以将这些信息上传至自己的服务器,这样就可以在你不知情的情况下伪造一些转账请求等信息。

    所以说,在没有安全保障的 Web 世界中,我们是没有隐私的,因此需要安全策略来保障我们的隐私和数据的安全。这也就是同源策略诞生的原因。

    同源策略

    Q: 什么是同源?
    A: 如果两个 URL 的协议、域名和端口都相同,我们就称这两个 URL 同源。比如下面这两个 URL,它们具有相同的协议 HTTPS、相同的域名 time.geekbang.org,以及相同的端口 443,所以我们就说这两个 URL 是同源的。

    https://time.geekbang.org/?category=1
    https://time.geekbang.org/?category=0
    

    Q: 什么是同源策略?
    A: 浏览器默认两个相同的源之间是可以相互访问资源和操作 DOM 的。两个不同的源之间若想要相互访问资源或者操作 DOM,那么会有一套基础的安全策略的制约,我们把这称为同源策略。

    具体来讲,同源策略主要表现在 DOM、Web 数据和网络这三个层面。

    第一个,DOM 层面。同源策略限制了来自不同源的 JavaScript 脚本对当前 DOM 对象读和写的操作。

    {
    let dom = opener.document
    dom.body.style.display = "none"
    }
    

    第二个,数据层面。同源策略限制了不同源的站点读取当前站点的 Cookie、IndexDB、LocalStorage 等数据。由于同源策略,我们依然无法通过第二个页面的 opener 来访问第一个页面中的 Cookie、IndexDB 或者 LocalStorage 等内容。

    opener.document.cookie
    

    第三个,网络层面。同源策略限制了通过 XMLHttpRequest 等方式将站点的数据发送给不同源的站点。

    var express = require("express");
    var app = express();
    app.use();
    
    app.get("/hello", function (req, res) {
      res.json(hello).end();
    });
    
    app.listen(3000, function () {
      console.log("Example app listening on port 3000!");
    });
    
    function handleHi() {
        axios.get("http://localhost:3000/hi").then((res) => {
          console.log("====================================");
          console.log(res);
          console.log("====================================");
        });
      }
    

    基于同源策略,采取的方式

    为了使项目能够得以开发和使用,我们可以采用以下方法:

    • 页面中可以嵌入第三方资源
      弊端:极易引发XSS攻击以及CSRF攻击
      解决方法:在浏览器中引入内容安全策略,称为 CSP。CSP 的核心思想是让服务器决定浏览器能够加载哪些资源,让服务器决定浏览器是否能够执行内联 JavaScript 代码。通过这些手段就可以大大减少 XSS 攻击。

    • 引入跨域资源共享策略(CORS)
      使用 XMLHttpRequest 和 Fetch 都是无法直接进行跨域请求的,因此浏览器又在这种严格策略的基础之上引入了跨域资源共享策略,让其可以安全地进行跨域操作

    • 在浏览器中实现跨文档消息机制
      可以通过 window.postMessage 的 JavaScript 接口来和不同源的 DOM 进行通信

    跨域资源共享(CORS)

    跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求

    简单请求
    某些请求不会触发 CORS 预检请求。本文称这样的请求为“简单请求”,请注意,该术语并不属于 Fetch (其中定义了 CORS)规范。若请求满足所有下述条件,则该请求可视为“简单请求”:

    • 使用下列方法之一:
      GET
      HEAD
      POST

    • Fetch 规范定义了对 CORS 安全的首部字段集合,不得人为设置该集合之外的其他首部字段。该集合为:
      Accept
      Accept-Language
      Content-Language
      Content-Type (需要注意额外的限制)
      DPR
      Downlink
      Save-Data
      Viewport-Width
      Width

    • Content-Type 的值仅限于下列三者之一:
      text/plain
      multipart/form-data
      application/x-www-form-urlencoded

    • 请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器;XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问。

    • 请求中没有使用 ReadableStream 对象。

    预检请求
    与前述简单请求不同,“需预检的请求”要求必须首先使用 OPTIONS 方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求(其中包括:当前网页所在的域名是否在服务器的许可名单之中(Access-Control-Allow-Origin)以及可以使用哪些HTTP动词和头信息字段(Access-Control-Allow-Methods、Access-Control-Allow-Headers))。"预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。

    • 使用了下面任一 HTTP 方法:
      PUT
      DELETE
      CONNECT
      OPTIONS
      TRACE
      PATCH

    • 人为设置了对 CORS 安全的首部字段集合之外的其他首部字段。该集合为:
      Accept
      Accept-Language
      Content-Language
      Content-Type (需要注意额外的限制)
      DPR
      Downlink
      Save-Data
      Viewport-Width
      Width

    • Content-Type 的值不属于下列之一:
      application/x-www-form-urlencoded
      multipart/form-data
      text/plain

    • 请求中的XMLHttpRequestUpload 对象注册了任意多个事件监听器。

    • 请求中使用了ReadableStream对象。

    预检请求完成之后,发送实际请求

    注:CORS 最初要求该行为,不过在后续的修订中废弃了这一要求。

    HTTP 响应首部字段

    1、Access-Control-Allow-Origin

    Access-Control-Allow-Origin: <origin> | *
    
    

    其中,origin 参数的值指定了允许访问该资源的外域 URI。对于不需要携带身份凭证的请求,服务器可以指定该字段的值为通配符,表示允许来自所有域的请求。

    2、Access-Control-Expose-Headers
    Access-Control-Expose-Headers 头让服务器把允许浏览器访问的头放入白名单,因为在跨域访问时,XMLHttpRequest对象的getResponseHeader()方法只能拿到一些最基本的响应头,Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma

    Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header
    

    3、Access-Control-Max-Age
    Access-Control-Max-Age 头指定了preflight请求的结果能够被缓存多久

    Access-Control-Max-Age: <delta-seconds>
    

    4、Access-Control-Allow-Credentials
    Access-Control-Allow-Credentials 响应头表示是否可以将对请求的响应暴露给页面。返回true则可以,其他值均不可以。
    Credentials可以是 cookies, authorization headers 或 TLS client certificates。

    Access-Control-Allow-Credentials: true
    

    虽可以用在对preflight预检测请求的响应中,但由于预检请求被废弃了,所以暂不讨论

    5、Access-Control-Allow-Methods
    Access-Control-Allow-Methods 首部字段用于预检请求的响应。其指明了实际请求所允许使用的 HTTP 方法。

    Access-Control-Allow-Methods: <method>[, <method>]*
    

    6、Access-Control-Allow-Headers
    Access-Control-Allow-Headers 首部字段用于预检请求的响应。其指明了实际请求中允许携带的首部字段。

    Access-Control-Allow-Headers: <field-name>[, <field-name>]*
    

    HTTP 请求首部字段

    1、Origin
    Origin 首部字段表明预检请求或实际请求的源站。

    Origin: <origin>
    

    2、Access-Control-Request-Method
    Access-Control-Request-Method 首部字段用于预检请求。其作用是,将实际请求所使用的 HTTP 方法告诉服务器。

    Access-Control-Request-Method: <method>
    

    3、Access-Control-Request-Headers
    Access-Control-Request-Headers 首部字段用于预检请求。其作用是,将实际请求所携带的首部字段告诉服务器。

    Access-Control-Request-Headers: <field-name>[, <field-name>]*
    

    JOSNP

    利用了使用src引用静态资源时不受跨域限制的机制。主要在客户端搞一个回调做一些参数接收与操作的处理,并把这个回调函数告知服务器,而服务器端需要做的是按照JavaScript的语法把数据放到约定好的回调函数之中即可
    它只支持get以及简单请求,兼容性好,相对来说不是很安全,因为它不是跨域规范,callback参数注入和资源访问授权设置未做限制。

    参考:浏览器工作原理与实践-同源策略
    HTTP访问控制(CORS)
    https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Server-Side_Access_Control

  • 相关阅读:
    IDEA快捷键:查询快捷键
    IDEA快捷键:自动代码(get、set、构造方法、try...catch、if....else、重写方法、实现方法、大小写转换、格式化、方法参数提示、方法的声明)
    查找(顺序查找、折半查找、分块查找)
    Springboot:整合Mybatis
    required a bean of type 'com.zhb.dao.StudentDao' that could not be found.
    Springboot:整合Druid
    Springboot:整合JDBC
    springboot、Thymeleaf、国际化的简单使用
    Exception evaluating SpringEL expression
    java8:四大核心函数式接口(消费型、供给型、函数型、断言型)
  • 原文地址:https://www.cnblogs.com/zppsakura/p/12839020.html
Copyright © 2011-2022 走看看