浏览器网络与安全

HTTP协议

HTTP/0.9

HTTP/0.9通信流程

  • 只有一个请求行,并没有 HTTP 请求头和请求体,因为只需要一个请求行就可以完整表达客户端的需求了。
  • 服务器也没有返回头信息,这是因为服务器端并不需要告诉客户端太多信息,只需要返回数据就可以了。
  • 返回的文件内容是以 ASCII 字符流来传输的,因为都是 HTML 格式的文件,所以使用 ASCII 字节码来传输是最合适的。

HTTP/1.0

  • 支持多种类型的文件下载是 HTTP/1.0 的一个核心诉求
    HTTP/1.0通信流程
  • 增加了请求头和响应头来支持多种不同类型的数据
    • 首先,浏览器需要知道服务器返回的数据是什么类型的,然后浏览器才能根据不同的数据类型做针对性的处理。
    • 其次,由于万维网所支持的应用变得越来越广,所以单个文件的数据量也变得越来越大。为了减轻传输性能,服务器会对数据进行压缩后再传输,所以浏览器需要知道服务器压缩的方法。
    • 再次,由于万维网是支持全球范围的,所以需要提供国际化的支持,服务器需要对不同的地区提供不同的语言版本,这就需要浏览器告诉服务器它想要什么语言版本的页面。
    • 最后,由于增加了各种不同类型的文件,而每种文件的编码形式又可能不一样,为了能够准确地读取文件,浏览器需要知道文件的编码类型。
  • 有的请求服务器可能无法处理,或者处理出错,这时候就需要告诉浏览器服务器最终处理该请求的情况,这就引入了状态码。状态码是通过响应行的方式来通知浏览器的。
  • 为了减轻服务器的压力,在 HTTP/1.0 中提供了 Cache 机制,用来缓存已经下载过的数据。
  • 服务器需要统计客户端的基础信息,比如 Windows 和 macOS 的用户数量分别是多少,所以 HTTP/1.0 的请求头中还加入了用户代理的字段

HTTP/1.1

  • 改进持久连接:在一个 TCP 连接上可以传输多个 HTTP 请求,只要浏览器或者服务器没有明确断开连接,那么该 TCP 连接会一直保持。浏览器为每个域名最多同时维护 6 个 TCP 持久连接。
  • 不成熟的 HTTP 管线化:HTTP/1.1 中试图通过管线化的技术来解决TCP队头阻塞的问题。虽然可以整批发送请求,不过服务器依然需要根据请求顺序来回复浏览器的请求,这样实际上又会造成HTTP请求的队头阻塞,也就是说,如果前面的请求得不到响应,后面的响应就不能发送。
  • 提供虚拟主机的支持:在 HTTP/1.0 中,每个域名绑定了一个唯一的 IP 地址,因此一个服务器只能支持一个域名。但是随着虚拟主机技术的发展,需要实现在一台物理主机上绑定多个虚拟主机,每个虚拟主机都有自己的单独的域名,这些单独的域名都公用同一个 IP 地址。因此,HTTP/1.1 的请求头中增加了 Host 字段,用来表示当前的域名地址,这样服务器就可以根据不同的 Host 值做不同的处理。
  • 对动态生成的内容提供支持:很多页面的内容都是动态生成的,因此在传输数据之前并不知道最终的数据大小,这就导致了浏览器不知道何时会接收完所有的文件数据。HTTP/1.1 通过引入 Chunk transfer 机制来解决这个问题,服务器会将数据分割成若干个任意大小的数据块,每个数据块发送时会附上该数据块的长度,最后使用一个零长度的块作为发送数据完成的标志。这样就提供了对动态内容的支持
  • 客户端cookie和安全机制
  • 存在的问题
    • 带宽利用率不高
      • TCP慢启动,导致首次渲染时间加长
      • 多条TCP连接会竞争带宽,但TCP连接之间又无法协商,导致关键资源的加载会被延迟
      • HTTP队头阻塞

HTTP/2.0

一个域名只使用一个TCP长连接
消除HTTP/1.1的队头阻塞问题,实现并行请求和响应
HTTP/2.0--TCP

多路复用

  • 请求和响应通过流ID确定对应关系,然后分帧传输,每一帧都有唯一的流ID对应着唯一的请求/响应流,具体是请求还是响应则取决于发送方。
  • 服务器和浏览器将相同ID的数据帧拼接为完整的HTTP数据
  • 服务器优先处理关键资源的请求
多路复用的实现

多路复用的二进制分帧层
引入二进制分帧层来处理请求/响应,帧的解析方式比文本的解析更容易有效。

HTTP/2 的请求和接收过程:

  • 首先,浏览器准备好请求数据,包括了请求行、请求头等信息,如果是 POST 方法,那么还要有请求体。这些数据经过二进制分帧层处理之后,会被转换为一个个带有请求 ID 编号的帧,通过协议栈将这些帧发送给服务器。
  • 服务器接收到所有帧之后,会将所有相同 ID 的帧合并为一条完整的请求信息。然后服务器处理该条请求,并将处理的响应行、响应头和响应体分别发送至二进制分帧层。
  • 同样,二进制分帧层会将这些响应数据转换为一个个带有请求 ID 编号的帧,经过协议栈发送给浏览器。
  • 浏览器接收到响应帧之后,会根据 ID 编号将帧的数据提交给对应的请求。

其他特性

  • 设置请求的优先级
  • 服务器推送资源
  • 首部压缩,请求和响应中公共首部不再发送,而是只发送索引,具体的首部内容在本地。

HTTP/3.0

HTTP协议存在的问题

  • TCP队头阻塞:为了保证数据包的顺序,若发生丢包事件,则需要重传该包以及之后的包。因为HTTP/2.0只使用一个TCP长连接,所以一旦丢包率增加,HTTP/2.0的效率反而会降低。
    TCP队头阻塞
  • HTTPS建立连接的时延:HTTPS建立连接的握手阶段会消耗3~4个RTT。

使用基于UDP的QUIC协议

HTTP/3.0--QUIC

  • 实现了类似 TCP 的流量控制、传输可靠性的功能。虽然 UDP 不提供可靠性的传输,但 QUIC 在 UDP 的基础之上增加了一层来保证数据可靠性传输。它提供了数据包重传、拥塞控制以及其他一些 TCP 中存在的特性。
  • 集成了 TLS 加密功能。目前 QUIC 使用的是 TLS1.3,相较于早期版本 TLS1.3 有更多的优点,其中最重要的一点是减少了握手所花费的 RTT 个数。
  • 实现了 HTTP/2 中的多路复用功能。和 TCP 不同,QUIC 实现了在同一物理连接上可以有多个独立的逻辑数据流
    QUIC的多路复用
  • 实现快速握手:由于 QUIC 是基于 UDP 的,所以 QUIC 可以实现使用 0-RTT 或者 1-RTT 来建立连接。

浏览器安全

页面安全

同源策略

页面安全的核心:同源策略

同源策略跨源网络访问的三种情况

  • 通常允许进行跨域写操作:例如链接(links),重定向以及表单提交。特定少数的HTTP请求需要添加 preflight
    • 比如提交表单这个写操作,表单不一定提交到提供网页页面的网站,很有可能提交到专门处理表单的服务器,如果不允许跨域写,将是很不灵活的;
    • 表单提交到什么地方,是编写页面时程序员决定,程序员不可能故意写一个恶意域名进去,所以写操作通常是安全的
  • 通常允许跨域资源嵌入<script><img><iframe><link><video><audio>等带有src属性的标签可以不遵守同源策略
    • 现在很多大型网站的js脚本、图片等都不是存放在存储网站页面的那台服务器上,他们很可能通过CDN等方式传送到浏览器端,如果限制他们必须和网站页面同源,无异于自己束缚手脚;
    • 一个网站要加载哪些脚本,由网站的编写人员说了算,他们不会故意加载恶意脚本(比如银行网站的编写人员不会将恶意网站的脚本写在银行网站中),所以只要是写在网页中的脚本,我们认为它是安全的;
    • 所以,a.com的网页中可以写,a网站加载了b网站的脚本,这是完全可以的,不受任何限制;
    • 可以这样认为,只要是页面加载的脚本,都和页面同源,无论这个脚本来自哪个”源”(source);
  • 通常不允许跨域读操作

同源策略对于JavaScript脚本的规定:

  • 浏览器在执行一个js脚本(或其他脚本)前,需要对这个脚本进行同源检测,如果加载这个脚本的页面和当前页面不同源,浏览器将拒绝执行此脚本
  • 浏览器并不关心js脚本来自何方(不关心js脚本从哪个域名、哪个”源”加载),它只关心加载脚本的那个页面是否和当前页面同源
同源策略体现在DOM、web数据和网络层面
  • DOM层面:不允许来自不同源的JavaScript脚本读写当前DOM对象,这里的不同源并不是指JavaScript脚本的来源,而是指JavaScript脚本所属页面的源。因此,加载CDN下的JavaScript脚本在当前页面下是允许访问DOM的。
  • web数据层面:不允许来自不同源的JavaScript脚本读写当前站点的cookie、IndexDB、LocalStorage等web数据
  • 网络层面:有的时候浏览器允许XMLHttpRequest请求发送到不同源的站点,服务器可以正常响应,但浏览器会拦截不同源的服务器结果,有的时候(如https协议)则不允许发出跨域请求
    • 使用JavaScript动态添加script、img等标签来加载不同源的资源,若加载的是脚本,该脚本可以执行。
    • 只有和本网页同源的脚本才会被执行,有时,AJAX已经加载不同源的脚本,但绝对不会被执行。这一点和资源嵌入不同,因为资源嵌入是由页面控制的行为,而AJAX是脚本控制的行为,脚本控制的行为通常并不可信。
跨域访问策略
更改document.domain
  • 浏览器在检测是否同源时,通过document.domain属性来获取当前页面域名,然后检测域名是否相同
  • document.domain属性不能随便更改,但可以通过JavaScript脚本将document.domain属性设置为当前域或当前域的父域
  • 此种跨域访问限制颇多
通过window.name获取string类型数据

一个窗口或标签不管跳转多少网站,window.name值是不变的,所以可以从window.name中获取string类型数据

JSONP
postMessage跨文档消息机制
  • postMessage()方法允许来自不同源的脚本(无视协议,端口,域名的不同)采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递
CORS跨域资源共享

跨域资源共享:允许一个域上的网络应用向另一个域提交跨域AJAX请求

OAuth跨域授权
CSP内容安全策略

由服务器来指定页面能够加载哪些资源,能够执行内联的JavaScript代码,这样即使是CDN加载资源也可能被阻止。

  • 指定加载资源的来源
  • 指定使用的协议
    使用 Content-Security-Policy HTTP首部或者meta标签
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
  • 想要所有内容均来自站点的同一个源 (不包括其子域名):Content-Security-Policy: default-src 'self'
  • 想要允许在邮件里包含HTML,同样图片允许从任何地方加载,但不允许JavaScript或者其他潜在的危险内容(从任意位置加载):Content-Security-Policy: default-src 'self' *.mailsite.com; img-src *。这个示例并未指定script-src。在此CSP示例中,站点通过 default-src 指令的对其进行配置,这也同样意味着脚本文件仅允许从原始服务器获取。

总之,跨域访问和内容安全策略基本上都是由服务器来控制浏览器的请求。

跨站脚本攻击(XSS)

黑客往HTML文件中或DOM中注入恶意脚本,用户在浏览页面时通过恶意脚本的执行(一般都是读取用户信息,使用跨域请求发送信息到恶意服务器)来实施攻击的手段。由于浏览器无法分辨JavaScript脚本是否恶意,因此恶意脚本拥有所有的脚本权限。

最初是通过跨域实现,而现在注入恶意脚本的方式很多,不止是跨域实现了。

跨站脚本攻击的行为
  • 窃取cookie信息,使用跨域请求将cookie发送到恶意服务器
  • 监听用户行为,获取用户的输入信息,如信用卡等信息
  • 修改DOM,伪造假的登录窗口,获取用户的用户名和密码
  • 生成浮窗广告,影响用户体验
恶意脚本注入的方式
  • 存储型XSS攻击
    存储型XSS攻击

    • 黑客利用站点漏洞将恶意JavaScript代码提交到网站的数据库中
    • 用户向网站请求了包含恶意脚本的页面
    • 当用户浏览页面时,恶意脚本执行
  • 反射型XSS攻击

    • 黑客将恶意JavaScript脚本通过网站请求发送给服务器,服务器返回的页面中就会包含了该恶意JavaScript脚本。
    • 比如,用户点击了伪造的恶意链接,恶意脚本就会通过请求发送,然后被服务器返回到链接的页面中加载,使得用户上当。
    • Web 服务器不会存储反射型 XSS 攻击的恶意脚本,这是和存储型 XSS 攻击不同的地方。
// node搭建的服务器程序

var express = require('express');
var router = express.Router();


/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express',xss:req.query.xss });
});


module.exports = router;

<!DOCTYPE html>
<html>
<head>
  <title><%= title %></title>
  <link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
  <h1><%= title %></h1>
  <p>Welcome to <%= title %></p>
  <div>
      <%- xss %>
  </div>
</body>
</html>

当打开http://localhost:3000/?xss=<script>alert(‘你被xss攻击了’)</script>这段 URL 时,就会加载执行alert('你被xss攻击了')脚本语句。

  • 基于DOM的XSS攻击
    • 不牵涉到服务器
    • 在网络传输的过程中劫持数据,修改HTML页面,如路由器劫持、本地恶意软件劫持等。
阻止XSS攻击

服务端安全漏洞:存储型XSS攻击、反射型XSS攻击
前端安全漏洞:基于DOM的XSS攻击

阻止XSS攻击的原则:

  • 阻止恶意脚本的注入
  • 阻止恶意跨域请求的发送
常用阻止XSS攻击的策略
  • 服务器对输入内容进行过滤或转码,对关键字符进行转义,如<script>标签转义等
  • 充分利用CSP策略
    • 限制加载其他域下的资源
    • 禁止向第三方域提交数据
    • 禁止执行内联脚本和未授权脚本
    • 提供上报机制
  • 使用HttpOnly属性保护cookie
    服务器在设置cookie时加入HttpOnly标志,这样cookie无法用JavaScript读取,只能在HTTP请求中使用。
set-cookie: NID=189=M8q2FtWbsR8RlcldPVt7qkrqR38LmFY9jUxkKo3-4Bi6Qu_ocNOat7nkYZUTzolHjFnwBw0izgsATSI7TZyiiiaV94qGh-BzEYsNVa7TZmjAYTxYTOM9L_-0CN9ipL6cXi8l6-z41asXtm2uEwcOC5oh9djkffOMhWqQrlnCtOI; expires=Sat, 18-Apr-2020 06:52:22 GMT; path=/; domain=.google.com; HttpOnly

跨站请求伪造(CSRF)

黑客诱惑用户打开黑客的网站,然后黑客利用用户的登录状态发起跨站请求

用户的登录状态一般都是cookie来保存,一旦cookie设置得不够安全,请求就会携带用户的cookie。

当打开黑客的页面后,一般有三种方式来实施CSRF攻击

  • 自动发起GET请求:如黑客请求隐藏在img标签内,当页面加载后,浏览器就会自动发起假的图片GET请求。

<!DOCTYPE html>
<html>
  <body>
    <h1>黑客的站点:CSRF攻击演示</h1>
    <img src="https://time.geekbang.org/sendcoin?user=hacker&number=100">
  </body>
</html>
  • 自动发起POST请求:当加载页面后,自动执行脚本中的提交隐藏表单信息。

<!DOCTYPE html>
<html>
<body>
  <h1>黑客的站点:CSRF攻击演示</h1>
  <form id='hacker-form' action="https://time.geekbang.org/sendcoin" method=POST>
    <input type="hidden" name="user" value="hacker" />
    <input type="hidden" name="number" value="100" />
  </form>
  <script> document.getElementById('hacker-form').submit(); </script>
</body>
</html>
  • 引诱用户点击链接:打开黑客的网站后,引诱用户点击链接,从而发起恶意请求

<div>
  <img width=150 src=http://images.xuejuzi.cn/1612/1_161230185104_1.jpg> </img> </div> <div>
  <a href="https://time.geekbang.org/sendcoin?user=hacker&number=100" taget="_blank">
    点击下载美女照片
  </a>
</div>
防止CSRF攻击
发起CSRF的必要条件
  • 目标站点一定要有 CSRF 漏洞(对第三方网站发起的请求不做判断);
  • 用户要登录过目标站点,并且在浏览器上保持有该站点的登录状态;
  • 需要用户打开一个第三方站点,可以是黑客的站点,也可以是一些论坛
阻止CSRF攻击
  • 充分利用Cookie的SameSite属性:来禁止从第三方站点发起请求的时候带上某些关键cookie数据。比如从B网站向A网站发起请求,B网站就是第三方网站,那么就需要禁止该请求携带A网站的关键cookie数据。
    • 在 HTTP 响应头中,通过 set-cookie 字段设置关键 Cookie 时,可以带上 SameSite 选项

set-cookie: 1P_JAR=2019-10-20-06; expires=Tue, 19-Nov-2019 06:36:21 GMT; path=/; domain=.google.com; SameSite=none
  • SameSite属性的值
    • strict:完全禁止从第三方网站发送请求时携带该cookie,防止CSRF攻击
    • lax:
      • 第三方站点的链接打开和从第三方站点提交 Get 方式的表单这两种方式都会携带 Cookie。
      • 第三方站点中使用 Post 请求,或者通过 img、iframe 等标签加载的 URL,这些场景都不会携带 Cookie
    • none:任何时候都会发送cookie
  • 验证请求的来源站点:服务器判断请求头的Referer和Origin属性,如果是第三方网站,则拒绝响应该请求。
  • 使用CSRF Token
    • 在首次登陆网站后,服务器返回一个CSRF Token(服务器生成的随机字符串),将该字符串植入到返回的页面中。
    • 在浏览器端如果要发起对该网站的请求,需要携带CSRF Token值,由服务器验证该Token是否合法。如果从第三方网站发起的请求,无法获取到CSRF Token值,则服务器验证会失败。

系统安全

多进程架构下的渲染进程与主进程
多进程架构在的渲染进程安全沙箱

  • 浏览器被划分为浏览器内核渲染内核两个核心模块,其中浏览器内核是由网络进程、浏览器主进程和 GPU 进程组成的,渲染内核就是渲染进程。
  • 所有的网络资源都是通过浏览器内核来下载的,下载后的资源会通过 IPC 将其提交给渲染进程(浏览器内核和渲染进程之间都是通过 IPC 来通信的)。
  • 渲染进程会对这些资源进行解析、绘制等操作,最终生成一幅图片。
  • 渲染进程并不负责将图片显示到界面上,而是将最终生成的图片提交给浏览器内核模块,由浏览器内核模块负责显示这张图片。

安全沙箱

  • 因为网络资源的内容存在着各种可能性,所以浏览器会默认所有的网络资源都是不可信的
  • 执行这些网络资源,比如解析 HTML、解析 CSS、执行 JavaScript、图片编解码等操作,就需要非常谨慎了
  • 将渲染进程和操作系统隔离的这道墙就是安全沙箱,将可能有恶意程序执行的进程与操作系统隔离。

浏览器中的安全沙箱是利用操作系统提供的安全技术,让渲染进程在执行过程中无法访问或者修改操作系统中的数据,在渲染进程需要访问系统资源的时候,需要通过浏览器内核来实现,然后将访问的结果通过 IPC 转发给渲染进程

安全沙箱对浏览器各个模块功能的影响

安全沙箱最小的保护单位是进程,并且能限制进程对操作系统资源的访问和修改,这就意味着如果要让安全沙箱应用在某个进程上,那么这个进程必须没有读写操作系统的功能,比如读写本地文件、发起网络请求、调用 GPU 接口等。

在渲染进程内部涉及到和系统交互的功能都转移到浏览器内核中去实现
渲染进程与浏览器内核的职责分配

  • 持久存储:浏览器将读写文件的操作全部放在了浏览器内核中实现,然后通过 IPC 将操作结果转发给渲染进程。
    • 存储 Cookie 数据的读写
      • 通常浏览器内核会维护一个存放所有 Cookie 的 Cookie 数据库,然后当渲染进程通过 JavaScript 来读取 Cookie 时,渲染进程会通过 IPC 将读取 Cookie 的信息发送给浏览器内核,浏览器内核读取 Cookie 之后再将内容返回给渲染进程。
    • 一些缓存文件的读写也是由浏览器内核实现的,比如网络文件缓存的读取。
  • 网络访问
    • 访问网络,需要通过浏览器内核。不过浏览器内核在处理 URL 请求之前,会检查渲染进程是否有权限请求该 URL,比如检查 XMLHttpRequest 或者 Fetch 是否是跨站点请求,或者检测 HTTPS 的站点中是否包含了 HTTP 的请求。
  • 用户交互
    • 渲染进程内部是无法直接操作窗口句柄的,这也是为了限制渲染进程监控到用户的输入事件
    • 操作系统没有将用户输入事件直接传递给渲染进程,而是将这些事件传递给浏览器内核。然后浏览器内核再根据当前浏览器界面的状态来判断如何调度这些事件,如果当前焦点位于浏览器地址栏中,则输入事件会在浏览器内核内部处理;如果当前焦点在页面的区域内,则浏览器内核会将输入事件转发给渲染进程。

站点隔离

同一站点(包含了相同的根域名和相同协议的URL)中相互关联的页面放到同一渲染进程。

目前所有操作系统都面临着两个 A 级漏洞——幽灵(Spectre)和熔毁(Meltdown),这两个漏洞是由处理器架构导致的,很难修补,黑客通过这两个漏洞可以直接入侵到进程的内部,如果入侵的进程没有安全沙箱的保护,那么黑客还可以发起对操作系统的攻击。

站点隔离:将标签级的渲染进程重构为 iframe 级的渲染进程,严格按照同一站点的策略来分配渲染进程。实现了站点隔离,就可以将恶意的 iframe 隔离在恶意进程内部,使得它无法继续访问其他 iframe 进程的内容,因此也就无法攻击其他站点了

网络安全

HTTPS:明文传输转为加密传输

使用对称加密

对称加密是指加密和解密都使用的是相同的密钥。
对称加密

密钥协商流程

HTTPS 首先要协商加解密方式,这个过程就是 HTTPS 建立安全连接的过程。为了让加密的密钥更加难以破解,我们让服务器和客户端同时决定密钥,具体过程如下:

  • 浏览器发送它所支持的加密套件列表和一个随机数 client-random,这里的加密套件是指加密的方法,加密套件列表就是指浏览器能支持多少种加密方法列表。
  • 服务器会从加密套件列表中选取一个加密套件,然后还会生成一个随机数 service-random,并将 service-random 和加密套件列表返回给浏览器。
  • 最后浏览器和服务器分别返回确认消息。

浏览器端和服务器端都有相同的 client-random 和 service-random 了,然后它们再使用相同的方法将 client-random 和 service-random 混合起来生成一个密钥 master secret,有了密钥 master secret 和加密套件之后,双方就可以进行数据的加密传输了。

缺点

传输 client-random 和 service-random 的过程却是明文的,黑客可以拿到协商的加密套件和双方的随机数,利用随机数合成密钥的算法合成密钥。

使用非对称加密

非对称加密算法有 A、B 两把密钥,如果你用 A 密钥来加密,那么只能使用 B 密钥来解密;反过来,如果你要 B 密钥来加密,那么只能用 A 密钥来解密。

公钥和私钥

在 HTTPS 中,服务器会将其中的一个密钥通过明文的形式发送给浏览器,我们把这个密钥称为公钥,服务器自己留下的那个密钥称为私钥。顾名思义,公钥是每个人都能获取到的,而私钥只有服务器才能知道,不对任何人公开。
非对称加密

密钥协商流程
  • 首先浏览器还是发送加密套件列表给服务器。
  • 然后服务器会选择一个加密套件,不过和对称加密不同的是,使用非对称加密时服务器上需要有用于浏览器加密的公钥和服务器解密 HTTP 数据的私钥,由于公钥是给浏览器加密使用的,因此服务器会将加密套件和公钥一道发送给浏览器。
  • 最后就是浏览器和服务器返回确认消息。

浏览器端有了服务器的公钥,在服务器端发送数据时,就可以使用该公钥来加密数据,只有服务器的私钥才能对该数据解密,保证了安全性。

缺点
  • 非对称加密的效率太低:非对称加密的算法复杂,效率低,这会严重影响到加解密数据的速度,进而影响到用户打开页面的速度。
  • 无法保证服务器发送给浏览器的数据安全:服务端数据只能使用私钥加密,由于公钥是公开的,因此服务端发送给浏览器的数据并不安全。当然,浏览器也可以生成公钥和私钥,与服务端进行公钥交换,但这又增加了一层复杂度。
使用非对称加密+对称加密

HTTPS使用了非对称加密+对称加密的组合策略:传输数据阶段依然使用对称加密,但是对称加密的密钥我们采用非对称加密来传输
非对称加密组合对称加密

密钥协商流程
  • 首先浏览器向服务器发送对称加密套件列表、非对称加密套件列表和随机数 client-random;
  • 服务器保存随机数 client-random,选择对称加密和非对称加密的套件,然后生成随机数 service-random,向浏览器发送选择的加密套件、service-random 和公钥;
  • 浏览器保存公钥,并生成随机数 pre-master,然后利用公钥对 pre-master 加密,并向服务器发送加密后的数据;
  • 最后服务器拿出自己的私钥,解密出 pre-master 数据,并返回确认消息。

服务器和浏览器就有了共同的 client-random、service-random 和 pre-master,然后服务器和浏览器会使用这三组随机数生成对称密钥,因为服务器和浏览器使用同一套方法来生成密钥,所以最终生成的密钥也是相同的。有了对称加密的密钥之后,双方就可以使用对称加密的方式来传输数据了。

数字证书:验证服务端身份

客户端为了避免DNS劫持导致的服务端身份伪造问题,需要对服务器的身份进行验证。

服务器使用权威机构颁发的证书,这个权威机构称为 CA(Certificate Authority),颁发的证书就称为数字证书(Digital Certificate)

对于浏览器来说,数字证书有两个作用

  • 验证身份:通过数字证书向浏览器证明服务器的身份
  • 获取公钥:数字证书里面包含了服务器公钥
完整的HTTPS请求流程

完整的HTTPS请求流程

  • 服务器没有直接返回公钥给浏览器,而是返回了数字证书,而公钥正是包含在数字证书中的;
  • 在浏览器端多了一个证书验证的操作,验证了证书之后,才继续后续流程。
数字证书包含的关键信息
  • 信息摘要:由CA使用HASH函数对网站提交的明文信息进行计算得到信息摘要
  • 数字签名:CA使用私钥对信息摘要进行加密得到的密文
浏览器验证数字证书
  • 读取证书中的网站明文信息,使用CA签名时相同的HASH函数计算得到摘要信息A
  • 使用CA的公钥解密数字签名,得到密文B。
  • 对比A和B,如果一致,则证书是合法的
  • 如果CA比较小众,浏览器不知道该不该信任它,则会按相同的验证方式验证该CA的上级CA(即给该CA颁发数字证书的CA)。通常,操作系统会内置信任的顶级CA证书(含公钥),如果CA链没有找到内置的顶级CA,则判定证书不合法。
  • 内置 CA 对应的证书称为根证书,根证书是最权威的机构,它们自己为自己签名,我们把这称为自签名证书。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值