前言
HTTP好比互联网中各种资源的搬运工,作为程序员的我们(不管你是哪方面的开发人员)都或多或少地会与其打交道,不管是在工作中还是面试中,我们都能看到它们的身影,所以HTTP的重要性不言而喻。前不久一个朋友在参加大大小小的面试中,基本上每个面试官都会问到,然后他跟我吐槽http知识点太多记不住。于是就有了这篇文章,在我的草稿箱里躺了一个多月才得以面世(ps:不知如何开头,然后各种事情...)!
HTTP/HTTPS相关知识点
TCP/IP
应用层
应用层决定了向用户提供应用服务时通信的活动。
传输层
传输层对上层应用层,提供处于网络连接中的两台计算机之间的数据传输。
网络层(网路互联层)
网络层用来处理在网络上流动的数据包,数据包是网络传输的最小数据单位,改层规定了通过怎样的路劲(所谓的传输路线)到达对方计算机,并把数据包传送给对方。
链路层(数据链路层,网络接口层)
用来处理连接网络的硬件部分。包括控制操作系统、硬件的设备驱动、网卡、光纤等等,硬件上的范畴均在链路层的作用范围。
重点聊一下DNS、TCP、UDP(敲黑板、划重点):
DNS协议
用户通常通过使用主机名或者域名来访问对方的计算机,而不是通过IP地址访问,所以DNS协议应运而生,提供提供域名到服务器IP地址之间的解析服务。
TCP协议
TCP协议提供可靠的字节流服务,可以将大块数据分割成报文段为单位的数据包进行管理,能够准确可靠地将数据传递给对方,为了准确无误地将数据送到目标处,TCP协议采用了三次握手策略。
发送端首先发送一个带SNY标志的数据包给对方。接收端收到后,回传一个带有SYN/ACK标志的数据包以示创达确认信息,最后发送端再回传一个带ACK标志的数据包,代表连接过程结束。
UDP协议
UDP协议与TCP协议一样用于处理数据包,不同的是:在传送数据前不需要先建立连接,正是因为如此,省去和很多的开销,使得它的速度比较快,一些对实时性要求较高的服务,通常使用的就是UDP协议。
PS:其它协议我就不码字了,问下度娘可以加深印象^_^
HTTP协议
http协议处于应用层,用于客户端与服务端之间的通信,不保存状态。所以Cookie就诞生了~
Cookie
HTTP是无状态协议,他不对之前发生过的请求和响应的状态进行管理,无法根据之前的状态进行本次的请求处理。 举个栗子:假设要求登录认证的web页面本身无法进行状态的管理,现在有100个客户端,分别向服务器端发送请求,服务器无法辨别对应的客户端,每次都需要客户端重新登录。
我们来看看开发中实际的报文: 1、第一次请求(请求报文中-没有Cookie信息状态)
sessionId
一般用来标记用户,session保存在服务端,而sessionId通过存放在cookie中来传输,sessionId在服务器端产生对应着登陆的用户。
HTTP报文
http请求报文
http响应报文
首部字段
http1.1规范了47种首部字段 通用首部字段
浏览器缓存机制
敲黑板、划重点
强缓存
强缓存是利用 http 头中的 Expires 和 Cache-Control 两个字段来控制的。强缓存中,当请求再次发出时,浏览器会根据其中的 expires 和 cache-control 判断目标资源是否“命中”强缓存,若命中返回的 HTTP 状态码为200则直接从缓存中获取资源,不会再与服务端发生通信。
从这样的描述中大家也不难猜测,expires 是有问题的,它最大的问题在于对“本地时间”的依赖。如果服务端和客户端的时间设置可能不同,或者我直接手动去把客户端的时间改掉,那么 expires 将无法达到我们的预期。
考虑到 expires 的局限性,HTTP1.1 新增了 Cache-Control 字段来完成 expires 的任务。 expires 能做的事情,Cache-Control 都能做;expires 完成不了的事情,Cache-Control 也能做。因此,Cache-Control 可以视作是 expires 的完全替代方案。 现在我们给 Cache-Control 字段一个特写:
如大家所见,在 Cache-Control 中,我们通过 max-age 来控制资源的有效期。max-age 不是一个时间戳,而是一个时间长度。在本例中,max-age 是 2592000 秒,它意味着该资源在 2592000 秒以内都是有效的,完美地规避了时间戳带来的潜在问题。
Cache-Control 应用分析
Cache-Control 的神通,可不止于这一个小小的 max-age。如下的用法也非常常见:
s-maxage 优先级高于 max-age,两者同时出现时,优先考虑 s-maxage。如果 s-maxage 未过期,则向代理服务器请求其缓存内容。
这个 s-maxage 不像 max-age 一样为大家所熟知。的确,在项目不是特别大的场景下,max-age 足够用了。但在依赖各种代理的大型架构中,我们不得不考虑代理服务器的缓存问题。s-maxage 就是用于表示 cache 服务器上(比如 cache CDN)的缓存的有效时间的,并只对 public 缓存有效。
public 与 private
public 与 private 是针对资源是否能够被代理服务缓存而存在的一组对立概念。
如果我们为资源设置了 public,那么它既可以被浏览器缓存,也可以被代理服务器缓存;如果我们设置了 private,则该资源只能被浏览器缓存。private 为默认值。但多数情况下,public 并不需要我们手动设置,比如有很多线上网站的 cache-control 是这样的:
no-store与no-cache
no-cache 绕开了浏览器:我们为资源设置了 no-cache 后,每一次发起请求都不会再去询问浏览器的缓存情况,而是直接向服务端去确认该资源是否过期(即走我们下文即将讲解的协商缓存的路线)。
no-store 比较绝情,顾名思义就是不使用任何缓存策略。在 no-cache 的基础上,它连服务端的缓存确认也绕开了,只允许你直接向服务端发送请求、并下载完整的响应。
协商缓存
协商缓存机制下,浏览器需要向服务器去询问缓存的相关信息,进而判断是重新发起请求、下载完整的响应,还是从本地获取缓存的资源。
如果服务端提示缓存资源未改动(Not Modified),资源会被重定向到浏览器缓存,这种情况下网络请求对应的状态码是 304(如下图)。
Last-Modified 与 Etag
Last-Modified 是一个时间戳,如果我们启用了协商缓存,它会在首次请求时随着 Response Headers 返回:
随后我们每次请求时,会带上一个叫 If-Modified-Since 的时间戳字段,它的值正是上一次 response 返回给它的 last-modified 值:
使用 Last-Modified 存在一些弊端,这其中最常见的就是这样两个场景:
1、我们编辑了文件,但文件的内容没有改变。服务端并不清楚我们是否真正改变了文件,它仍然通过最后编辑时间进行判断。因此这个资源在再次被请求时,会被当做新资源,进而引发一次完整的响应——不该重新请求的时候,也会重新请求。 2、当我们修改文件的速度过快时(比如花了 100ms 完成了改动),由于 If-Modified-Since 只能检查到以秒为最小计量单位的时间差,所以它是感知不到这个改动的——该重新请求的时候,反而没有重新请求了。
这两个场景其实指向了同一个 bug——服务器并没有正确感知文件的变化。为了解决这样的问题,Etag 作为 Last-Modified 的补充出现了
Etag 是由服务器为每个资源生成的唯一的标识字符串,这个标识字符串是基于文件内容编码的,只要文件内容不同,它们对应的 Etag 就是不同的,反之亦然。因此 Etag 能够精准地感知文件的变化。 Etag 和 Last-Modified 类似,当首次请求时,我们会在响应头里获取到一个最初的标识符字符串,它可以是这样的:
HTTPS
一张图告诉你区别:
HTTPS并非是应用层的一种新协议。只是HTTP通信接口部分用SSL(Secure Socket Layer) 和TLS(Transport Layer Security)协议代替而已,SSL与TLS在传输层与应用层之间对网络连接进行加密。 SSL/TLS:是为网络通信提供安全及数据完整性的一种安全协议. SSL:采用公开密钥加密(非对称加密算法)的处理方式来保证网络通信的安全,公开密钥加密使用一对非对称的密钥,一把叫做公开密钥,另一把叫私有密钥。
HTTP状态码
状态码:当客户端向服务器端发送请求时,描述返回的请求结果,用户可以根据状态码判断服务器是正常处理了请求还是出现了错误。 状态码类别如下:
HTTP版本
上面提到的HTTP都是基于HTTP1.1(目前使用最广泛的版本)
HTTP/2.0
HTTP2.0基于SPDY,主要是改善了数据传输的性能和安全性!
- 二进制编码:请求数据与相应数据采用二进制编码,分割成多个帧进行传输,效率更高
- 报文首部压缩:报文首部采用“HPACK”算法,在客户端和服务端两端建立“字典”,用索引号表示重复的字符串,对于相同的数据,不用重复请求和相应发送,减少冗余数据;采用哈夫曼编码压缩整数和字符串,可以达到50%~90%的压缩率。
- 多路由复用:同域名下所有通信都是在单个连接上完成,单个连接可以承载任意数量的双向数据流
HTTP/2.0:
HTTP/2 的缺点:
-
TCP以及TCP+TLS建立连接开销 1、建立TCP连接需要和服务器进行三次握手来确认连接成功,需要消耗1.5个RTT之后才能进行数据传输. 2、进行TLS连接,TLS有两个版本——TLS1.2和TLS1.3,每个版本建立连接所花的时间不同,大致是需要1~2个RTT.
-
TCP的队头阻塞问题 TCP为了保证可靠传输,有个“丢包重传”机制,丢失的包必须要等待重新传输确认,HTTP/2出现丢包时,整个TCP 都要开始等待重传。
HTTP/3.0
由于HTTP/2.0的缺陷,Google在推SPDY的时候就已经意识到了这些问题,于是就有了基于 UDP协议的“QUIC”协议,让HTTP跑在QUIC上而不是TCP上。它在HTTP/2的基础上又实现了质的飞跃,真正“完美”地解决了“队头阻塞”问题。 QUIC协议:
- QUIC在UDP的基础之上增加了一层来保证数据可靠性传输,提供了数据包重传、拥塞控制以及其他一些TCP中存在的特性
- QUIC可以实现使用0-RTT或者1-RTT来建立连接,这意味着QUIC可以用最快的速度来发送和接收数据
- QUIC实现了在同一物理连接上可以有多个独立的逻辑数据流。实现了数据流的单独传输,就解决了TCP中队头阻塞的问题
网络安全-Web攻击类型
SQL注入攻击与OS命令注入攻击
a、攻击者设置好攻击连接,引诱用户触发连接 b、执行恶意代码后,用户所持有的Cookie被窃取,用户权限被恶意使用 c、执行攻击命令操作服务器上数据资源 防护策略: 1、不要使用动态SQL:避免将用户提供的输入直接放入SQL语句中;最好使用准备好的语句和参数化查询,这样更安全。 2、限制数据库权限和特权:将数据库用户的功能设置为最低要求;这将限制攻击者在设法获取访问权限时可以执行的操作 3、不要将敏感数据保留在纯文本中,加密存储在数据库中的私有/机密数据
跨站脚本攻击(XSS)
通过存在安全漏洞的Web网站注册用户浏览运行非法的HTML标签或JavaScript进行攻击。最常见的攻击之一:在提交的表单里输入非法脚本进行攻击。 防护策略: 对提交的所有内容和url中的参数进行过滤,过滤掉特殊字符,然后对动态输出到页面的内容进行html编码,使脚本无法在浏览器中执行。
跨站点请求伪造(CSRF)
攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。
典型的攻击流程:
-
受害者登录a.com,并保留了登录凭证(Cookie)。
-
攻击者引诱受害者访问了b.com。
-
b.com 向 a.com 发送了一个请求:a.com/act=xx。浏览器会默认携带a.com的Cookie。
-
a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求。
-
a.com以受害者的名义执行了act=xx。
-
攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作。 防护策略:
-
同源检测:阻止不明外域的访问
-
提交时要求附加本域才能获取的信息(CSRF Token)
会话劫持
攻击者通过某种手段拿到了用户的会话ID,并使用此会话ID伪装成用户,到达攻击目的。
防护策略:
- 设置HttpOnly:通过设置Cookie的HttpOnly为true,可以防止客户端脚本访问这个Cookie,从而有效的防止XSS攻击
- 加入Token校验:用于检测请求的一致性
总结
通过思维导图、流程图的形式将基础知识点串联成面,形成自己的知识体系。码字不易,望朋友们随手点个赞,谢谢~ (PS:HTTP的知识点实在是太多了,仅靠一篇文章做到面面俱到不太现实)
参考书籍或文章
- 图解HTTP
- 前端性能优化原理与实践
- 解读HTTP/2与HTTP/3 的新特
转载请注明出处,商用请征得作者本人同意,谢谢!!!