HTTP基础

219 阅读22分钟

1. 浏览器输入一个URL的整体过程

  1. 当我们在浏览器地址栏按下键盘的时候,浏览器就会启动一个算法去书签栏和历史记录中按照我们输入的字母进行筛选、展示一个我们可能会访问的URL

  2. 当我们选定了URL按下回车时,浏览器就会开始构建请求行,然后检测这个域名是否合法,如果合法就将此任务给网络请求线程 构建好请求行后就会去检测强缓存是否有效(这个步骤不会发送网络请求),如果无效,就会开始调用DNS协议进行域名解析,如果之前访问过这个URL,那么浏览器会把DNS解析后的IP地址保存下来,下次访问就直接命中(大概可以节约50~200ms),如果没有就需要去网络运营商或者DNS服务器上寻找

  3. 拿到DNS解析的IP地址后,就会构建HTTP请求,开始TCP三次握手建立稳定链接:客户端向服务器发送一个SYN(同步序列编码),服务端收到后返回一个新的SYN + ACK(在第一个SYN上做计算后生成的回复消息),客户端收到后回复一个ACK,三次握手建立完毕。为什么是三次?两次太少,四次太多

  4. 建立好三次握手后,TCP协议为了传输方便,会将HTTP报文切割并编码成一个个数据包,随后转交给网络层

  5. 网络层拿到这些数据包后,通过IP地址,配合ARP协议反查出MAC地址,开始传输数据

  6. 服务器收到这些数据后,将在TCP传输层协议中被分割的报文还原成完整的,这个时候一般会校验是否有权限、是否设置了缓存以及是否过期等。如果设置了协商缓存,那么会返回304状态码通知浏览器使用协商缓存(这里可以把协商缓存的字段也说下),否则开始响应。响应完毕后,服务器会判断Connection字段是否为keep-alive(在HTTP 1.1中是默认值),不是则断开

  7. 接下来就是浏览器开始解析请求到的文件,首先调用GUI线程并行解析HTML和CSS文件,对HTML文件使用标记化和建树算法,根据文件中设置的标准来生成DOM树,对CSS文件进行格式化和标准化生成CSSOM树,最后合并成合成树。注意HTML和CSS文件解析是互不影响的,但是会影响最后的合成树生成的速度,所以CSS文件中不要放@import,它总是在CSS文件解析完毕后再去加载对应的资源 另外GUI线程和JS线程是互斥的,当解析到HTML文件中的script标签时,就会挂起GUI线程,从而阻塞渲染,所以script标签中不要写async,它总是异步加载,然后立即执行,但你可以写defer

  8. 拿到合成树后,为了提高渲染效率,因为复杂的图层总是会由GUP单独绘制(GPU加速),不会影响其他的图层,所以开始创建图层树。普通文档流可以算是复杂图层,除此之外absolute、transform、opacity、canvas等元素都能形成复杂图层,所以说动画最好放在absolute等元素上、用transform代替left/top

  9. 浏览器将这些图层的绘制生成一个个绘制指令,然后交给合成池去进行绘制,生成图块和位图,最后显示出当前的页面

2. 浏览器页面渲染过程

构建 DOM 树、样式计算、布局阶段、分层、绘制、分块、光栅化和合成

  1. HTML和CSS经过各自解析,生成DOM树和CSSOM树
  2. 合并成为渲染树
  3. 根据渲染树进行布局
  4. 最后调用GPU进行绘制,显示在屏幕上

3. 浏览器白屏机制

  1. 网络阶段,比如第一次访问没有缓存DNS对应的IP地址,网站设置了301跳转等等

  2. 渲染阶段。我们知道浏览器在拿到文件后会将它们解析成对应的DOM和CSSOM,这里有两个方面:

    • 第一个方面,由于浏览器的GUI渲染线程和JS线程互斥,所以碰到script标签就会先对JS文件进行解析,从而阻塞渲染,所以要注意书写的位置;
    • 第二个方面,如果CSS文件中有@import,那么它会在CSS解析完毕后再进行加载,同样会造成阻塞。

4. OSI七层模型,TCP/IP和HTTP分别位于哪一层

模型概述单位
物理层网络连接介质,如网线、光缆,数据在其中以比特为单位传输bit
数据链路层数据链路层将比特封装成数据帧并传递
网络层定义IP地址,定义路由功能,建立主机到主机的通信数据包
传输层负责将数据进行可靠或者不可靠传递,建立端口到端口的通信数据段
会话层控制应用程序之间会话能力,区分不同的进程------------
表示层数据格式标识,基本压缩加密功能------------
应用层各种应用软件------------

4.1 TCP 三次握手

  • 1.第一次握手:起初两端都处于CLOSED关闭状态,Client将标志位SYN置为1,随机产生一个值seq=x,并将该数据包发送给Server,Client进入SYN-SENT状态,等待Server确认;

  • 2.第二次握手:Server收到数据包后由标志位SYN=1得知Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=x+1,随机产生一个值seq=y,并将该数据包发送给Client以确认连接请求,Server进入SYN-RCVD状态,此时操作系统为该TCP连接分配TCP缓存和变量;

  • 3.第三次握手:Client收到确认后,检查ack是否为x+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=y+1,并且此时操作系统为该TCP连接分配TCP缓存和变量,并将该数据包发送给Server,Server检查ack是否为y+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client和Server就可以开始传输数据。

4.2 为什么三次握手,四次挥手

  • 四次挥手

    • 1.因为是双方彼此都建立了连接,因此双方都要释放自己的连接,A向B发出一个释放连接请求,他要释放链接表明不再向B发送数据了,此时B收到了A发送的释放链接请求之后,给A发送一个确认,A不能再向B发送数据了,它处于FIN-WAIT-2的状态,但是此时B还可以向A进行数据的传送。此时B向A 发送一个断开连接的请求,A收到之后给B发送一个确认。此时B关闭连接。A也关闭连接。
    • 2.为什么要有TIME-WAIT这个状态呢,这是因为有可能最后一次确认丢失,如果B此时继续向A发送一个我要断开连接的请求等待A发送确认,但此时A已经关闭连接了,那么B永远也关不掉了,所以我们要有TIME-WAIT这个状态。
    • 当然TCP也并不是100%可靠的。
  • 1.三次握手:为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误

4.3 CDN 原理

CDN的全称是Content Delivery Network,即内容分发网络。CDN的基本原理是广泛采用各种缓存服务器,将这些缓存服务器分布到用户访问相对集中的地区或网络中,在用户访问网站时,利用全局负载技术将用户的访问指向距离最近的工作正常的缓存服务器上,由缓存服务器直接响应

4.4 DNS 解析

  • 浏览器缓存:浏览器会按照一定的频率缓存 DNS 记录。
  • 操作系统缓存:如果浏览器缓存中找不到需要的 DNS 记录,那就去操作系统中找。
  • 路由缓存:路由器也有 DNS 缓存。
  • ISP 的 DNS 服务器:ISP 是互联网服务提供商(Internet Service Provider)的简称,ISP 有专门的 DNS 服务器应对 DNS 查询请求。
  • 根服务器:ISP 的 DNS 服务器还找不到的话,它就会向根服务器发出请求,进行递归查询(DNS 服务器先问根域名服务器.com 域名服务器的 IP 地址,然后再问.baidu 域名服务器,依次类推)

4.5 网络协议

TCP

传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由 IETF 的 RFC 793 定义。

  • 基于流的方式
  • 面向连接
  • 丢包重传
  • 保证数据顺序

UDP

Internet 协议集支持一个无连接的传输协议,该协议称为用户数据报协议(UDP,User Datagram Protocol)。UDP 为应用程序提供了一种无需建立连接就可以发送封装的 IP 数据包的方法。RFC 768 描述了 UDP。

  • UDP 是非连接的协议,也就是不会跟终端建立连接
  • UDP 包信息只有 8 个字节
  • UDP 是面向报文的。既不拆分,也不合并,而是保留这些报文的边界
  • UDP 可能丢包
  • UDP 不保证数据顺序

HTTP

  • HTTP/0.9:GET,无状态的特点形成
  • HTTP/1.0:支持 POST,HEAD,添加了请求头和响应头,支持任何格式的文件发送,添加了状态码、多字符集支持、多部分发送、权限、缓存、内容编码等
  • HTTP/1.1:默认长连接,同时 6 个 TCP 连接,CDN 域名分片
  • HTTPS:HTTP + TLS( 非对称加密 与 对称加密 )
    • 1.客户端发出 https 请求,请求服务端建立 SSL 连接
    • 2.服务端收到 https 请求,申请或自制数字证书,得到公钥和服务端私钥,并将公钥发送给客户端
    • 3.户端验证公钥,不通过验证则发出警告,通过验证则产生一个随机的客户端私钥
    • 4.客户端将公钥与客户端私钥进行对称加密后传给服务端
    • 5.服务端收到加密内容后,通过服务端私钥进行非对称解密,得到客户端私钥
    • 6.服务端将客户端私钥和内容进行对称加密,并将加密内容发送给客户端
    • 7.客户端收到加密内容后,通过客户端私钥进行对称解密,得到内容
  • HTTP/2.0:多路复用(一次 TCP 连接可以处理多个请求),服务器主动推送,stream 传输。
  • HTTP/3:基于 UDP 实现了 QUIC 协议
    • 建立好 HTTP2 连接
    • 发送 HTTP2 扩展帧
    • 使用 QUIC 建立连接
    • 如果成功就断开 HTTP2 连接
    • 升级为 HTTP3 连接

注:RTT = Round-trip time

4.6 TCP和UDP的区别

  • 1.UDP
    • 1.无连接
    • 2.面向报文,只是报文的搬运工
    • 3.不可靠,没有拥塞控制
    • 4.高效,头部开销只有8字节
    • 5.支持一对一、一对多、多对多、多对一
    • 6.适合直播、视频、语音、会议等实时性要求高的
  • 2.TCP
    • 1.面向连接:传输前需要先连接
    • 2.可靠的传输
    • 3.流量控制:发送方不会发送速度过快,超过接收方的处理能力
    • 4.拥塞控制:当网络负载过多时能限制发送方的发送速率
    • 5.不提供时延保障
    • 6.不提供最小带宽保障

5. http知识

5.1 常见HTTP状态码有哪些

1XX开头

  • 100:等待后续处理,比如POST请求发送大实体数据时

2xx 开头(请求成功)

  • 200 OK:客户端发送给服务器的请求被正常处理并返回
  • 204:请求成功处理,但没有返回任何实体部分

3xx 开头(重定向)

  • 301 Moved Permanently:永久重定向,请求的网页已永久移动到新位置。 服务器返回此响应时,会自动将请求者转到新位置
  • 302 Moved Permanently:临时重定向,请求的网页已临时移动到新位置。服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求
  • 304 Not Modified:未修改,自从上次请求后,请求的网页未修改过。服务器返回此响应时,不会返回网页内容

4xx 开头(客户端错误)

  • 400 Bad Request:错误请求,服务器不理解请求的语法,常见于客户端传参错误
  • 401 Unauthorized:未授权,表示发送的请求需要有通过 HTTP 认证的认证信息,常见于客户端未登录
  • 403 Forbidden:禁止,服务器拒绝请求,常见于客户端权限不足
  • 404 Not Found:未找到,服务器找不到对应资源

5xx 开头(服务端错误)

  • 500 Inter Server Error:服务器内部错误,服务器遇到错误,无法完成请求
  • 501 Not Implemented:尚未实施,服务器不具备完成请求的功能
  • 502 Bad Gateway:作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。
  • 503 service unavailable:服务不可用,服务器目前无法使用(处于超载或停机维护状态)。通常是暂时状态。

5.2 GET请求和POST请求有何区别

标准答案:

  • GET请求参数放在URL上,POST请求参数放在请求体里
  • GET请求参数长度有限制,POST请求参数长度可以非常大
  • POST请求相较于GET请求安全一点点,因为GET请求的参数在URL上,且有历史记录
  • GET请求能缓存,POST不能

更进一步:

其实HTTP协议并没有要求GET/POST请求参数必须放在URL上或请求体里,也没有规定GET请求的长度,目前对URL的长度限制,是各家浏览器设置的限制。GET和POST的根本区别在于:GET请求是幂等性的,而POST请求不是

幂等性,指的是对某一资源进行一次或多次请求都具有相同的副作用。例如搜索就是一个幂等的操作,而删除、新增则不是一个幂等操作。

由于GET请求是幂等的,在网络不好的环境中,GET请求可能会重复尝试,造成重复操作数据的风险,因此,GET请求用于无副作用的操作(如搜索),新增/删除等操作适合用POST

参考资料:HTTP|GET 和 POST 区别?网上多数答案都是错的

5.3 HTTP的请求报文由哪几部分组成

一个HTTP请求报文由请求行(request line)、请求头(header)、空行和请求数据4个部分组成 响应报文和请求报文结构类似

5.4 HTTP常见请求/响应头及其含义

通用头(请求头和响应头都有的首部)

请求头

响应头

实体头(针对请求报文和响应报文的实体部分使用首部)

HTTP首部当然不止这么几个,但为了避免写太多大家记不住(主要是别的我也没去看),这里只介绍了一些常用的,详细的可以看MDN的文档

5.5 HTTP/1.0和HTTP/1.1有什么区别

  • 长连接: HTTP/1.1支持长连接和请求的流水线,在一个TCP连接上可以传送多个HTTP请求,避免了因为多次建立TCP连接的时间消耗和延时
  • 缓存处理: HTTP/1.1引入Entity tag,If-Unmodified-Since, If-Match, If-None-Match等新的请求头来控制缓存,详见浏览器缓存小节
  • 带宽优化及网络连接的使用: HTTP1.1则在请求头引入了range头域,支持断点续传功能
  • Host头处理: 在HTTP/1.0中认为每台服务器都有唯一的IP地址,但随着虚拟主机技术的发展,多个主机共享一个IP地址愈发普遍,HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会400错误

5.6 介绍一下HTTP/2.0新特性

  • 多路复用: 即多个请求都通过一个TCP连接并发地完成
  • 服务端推送: 服务端能够主动把资源推送给客户端
  • 新的二进制格式: HTTP/2采用二进制格式传输数据,相比于HTTP/1.1的文本格式,二进制格式具有更好的解析性和拓展性
  • header压缩: HTTP/2压缩消息头,减少了传输数据的大小

5.7 说说HTTP/2.0多路复用基本原理以及解决的问题

HTTP/2解决的问题,就是HTTP/1.1存在的问题:

  • TCP慢启动: TCP连接建立后,会经历一个先慢后快的发送过程,就像汽车启动一般,如果我们的网页文件(HTML/JS/CSS/icon)都经过一次慢启动,对性能是不小的损耗。另外慢启动是TCP为了减少网络拥塞的一种策略,我们是没有办法改变的。
  • 多条TCP连接竞争带宽: 如果同时建立多条TCP连接,当带宽不足时就会竞争带宽,影响关键资源的下载。
  • HTTP/1.1队头阻塞: 尽管HTTP/1.1长链接可以通过一个TCP连接传输多个请求,但同一时刻只能处理一个请求,当前请求未结束前,其他请求只能处于阻塞状态。

为了解决以上几个问题,HTTP/2一个域名只使用一个TCP⻓连接来传输数据,而且请求直接是并行的、非阻塞的,这就是多路复用

实现原理: HTTP/2引入了一个二进制分帧层,客户端和服务端进行传输时,数据会先经过二进制分帧层处理,转化为一个个带有请求ID的帧,这些帧在传输完成后根据ID组合成对应的数据。

5.8 说说HTTP/3.0

尽管HTTP/2解决了很多1.1的问题,但HTTP/2仍然存在一些缺陷,这些缺陷并不是来自于HTTP/2协议本身,而是来源于底层的TCP协议,我们知道TCP链接是可靠的连接,如果出现了丢包,那么整个连接都要等待重传,HTTP/1.1可以同时使用6个TCP连接,一个阻塞另外五个还能工作,但HTTP/2只有一个TCP连接,阻塞的问题便被放大了。

由于TCP协议已经被广泛使用,我们很难直接修改TCP协议,基于此,HTTP/3选择了一个折衷的方法——UDP协议,HTTP/2在UDP的基础上实现多路复用、0-RTT、TLS加密、流量控制、丢包重传等功能。

参考资料:http发展史(http0.9、http1.0、http1.1、http2、http3)梳理笔记 (推荐阅读)

5.9 HTTP和HTTPS有何区别

  • HTTPS使用443端口,而HTTP使用80
  • HTTPS需要申请证书
  • HTTP是超文本传输协议,是明文传输;HTTPS是经过SSL加密的协议,传输更安全
  • HTTPS比HTTP慢,因为HTTPS除了TCP握手的三个包,还要加上SSL握手的九个包

5.10 HTTPS是如何进行加密的

我们通过分析几种加密方式,层层递进,理解HTTPS的加密方式以及为什么使用这种加密方式:

对称加密

客户端和服务器公用一个密匙用来对消息加解密,这种方式称为对称加密。客户端和服务器约定好一个加密的密匙。客户端在发消息前用该密匙对消息加密,发送给服务器后,服务器再用该密匙进行解密拿到消息。 这种方式一定程度上保证了数据的安全性,但密钥一旦泄露(密钥在传输过程中被截获),传输内容就会暴露,因此我们要寻找一种安全传递密钥的方法。

非对称加密

采用非对称加密时,客户端和服务端均拥有一个公钥和私钥,公钥加密的内容只有对应的私钥能解密。私钥自己留着,公钥发给对方。这样在发送消息前,先用对方的公钥对消息进行加密,收到后再用自己的私钥进行解密。这样攻击者只拿到传输过程中的公钥也无法破解传输的内容 尽管非对称加密解决了由于密钥被获取而导致传输内容泄露的问题,但中间人仍然可以用篡改公钥的方式来获取或篡改传输内容,而且非对称加密的性能比对称加密的性能差了不少

第三方认证

上面这种方法的弱点在于,客户端不知道公钥是由服务端返回,还是中间人返回的,因此我们再引入一个第三方认证的环节:即第三方使用私钥加密我们自己的公钥,浏览器已经内置一些权威第三方认证机构的公钥,浏览器会使用第三方的公钥来解开第三方私钥加密过的我们自己的公钥,从而获取公钥,如果能成功解密,就说明获取到的自己的公钥是正确的 但第三方认证也未能完全解决问题,第三方认证是面向所有人的,中间人也能申请证书,如果中间人使用自己的证书掉包原证书,客户端还是无法确认公钥的真伪

数字签名

为了让客户端能够验证公钥的来源,我们给公钥加上一个数字签名,这个数字签名是由企业、网站等各种信息和公钥经过单向hash而来,一旦构成数字签名的信息发生变化,hash值就会改变,这就构成了公钥来源的唯一标识。 具体来说,服务端本地生成一对密钥,然后拿着公钥以及企业、网站等各种信息到CA(第三方认证中心)去申请数字证书,CA会通过一种单向hash算法(比如MD5),生成一串摘要,这串摘要就是这堆信息的唯一标识,然后CA还会使用自己的私钥对摘要进行加密,连同我们自己服务器的公钥一同发送给我我们。 浏览器拿到数字签名后,会使用浏览器本地内置的CA公钥解开数字证书并验证,从而拿到正确的公钥。由于非对称加密性能低下,拿到公钥以后,客户端会随机生成一个对称密钥,使用这个公钥加密并发送给服务端,服务端用自己的私钥解开对称密钥,此后的加密连接就通过这个对称密钥进行对称加密。 综上所述,HTTPS在验证阶段使用非对称加密+第三方认证+数字签名获取正确的公钥,获取到正确的公钥后以对称加密的方式通信

参考资料:看图学HTTPS

6. 前端安全

6.1 CSRF

什么是CSRF攻击

  • CSRF即Cross-site request forgery(跨站请求伪造),是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。

假如黑客在自己的站点上放置了其他网站的外链,例如 www.weibo.com/api,默认情况下,浏览器会带着weibo.com的cookie访问这个网址,如果用户已登录过该网站且网站没有对CSRF攻击进行防御,那么服务器就会认为是用户本人在调用此接口并执行相关操作,致使账号被劫持。

如何防御CSRF攻击

  • 验证Token:浏览器请求服务器时,服务器返回一个token,每个请求都需要同时带上token和cookie才会被认为是合法请求
  • 验证Referer:通过验证请求头的Referer来验证来源站点,但请求头很容易伪造
  • 设置SameSite:设置cookie的SameSite,可以让cookie不随跨域请求发出,但浏览器兼容不一

6.2 XSS

什么是XSS攻击

  • XSS即Cross Site Scripting(跨站脚本),指的是通过利用网页开发时留下的漏洞,注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。常见的例如在评论区植入JS代码,用户进入评论页时代码被执行,造成页面被植入广告、账号信息被窃取

XSS攻击有哪些类型

  • 存储型:即攻击被存储在服务端,常见的是在评论区插入攻击脚本,如果脚本被储存到服务端,那么所有看见对应评论的用户都会受到攻击。
  • 反射型:攻击者将脚本混在URL里,服务端接收到URL将恶意代码当做参数取出并拼接在HTML里返回,浏览器解析此HTML后即执行恶意代码
  • DOM型:将攻击脚本写在URL中,诱导用户点击该URL,如果URL被解析,那么攻击脚本就会被运行。和前两者的差别主要在于DOM型攻击不经过服务端

如何防御XSS攻击

  • 输入检查:对输入内容中的<script><iframe>等标签进行转义或者过滤
  • 设置httpOnly:很多XSS攻击目标都是窃取用户cookie伪造身份认证,设置此属性可防止JS获取cookie
  • 开启CSP,即开启白名单,可阻止白名单以外的资源加载和运行

7. 前端更新机制

  • 更新了元素的几何属性(重排)
  • 更新元素的绘制属性(重绘)
  • 直接合成
    • CSS3 的属性可以直接跳到这一步