http 相关
Http 协议的演变
1、HTTP/1.0 到 HTTP/1.1 :主要实现了对 TCP 连接的复用
HTTP/1.1 中引入了持久连接的概念,通过设置 Connection
头部为 keep-alive
的方式,可以让 TCP 连接不会关闭。
该功能避免了 TCP 连接的重新建立,客户端可在已建立的 TCP 连接上,长时间地对同一个服务端的发起请求。
2、HTTP/1.1 到 HTTP/2:主要实现了多个请求的复用
HTTP/2 通过将 HTTP 消息拆分为独立的帧,进行交错发送,实现在同一个连接上并行多个请求,来减少网络请求的延迟。
为了实现多路复用,HTTP/2 协议对 HTTP 头部进行了二进制编码,因此不再语义可读。
除此之外,HTTP2 还实现了 Header 压缩、服务端主动推动、流优先级等能力。
3、HTTP/2 到 HTTP/3:主要实现了基于 UDP 协议、更快的传输。
HTTP/3 使用了基于 UDP 的 QUIC 协议,实现了又快又可靠的传输。
由于 UDP 协议中没有错误检查内容,因此可以更快地实现通信。
同时,QUIC 协议负责合并纠错、重建丢失的数据,解决了 UDP 协议传输丢包的问题
使用场景:游戏、直播
http 缓存
https://www.cnblogs.com/wonyun/p/5524617.html
强缓存与协商缓存的区别,可以用下表来进行描述:
名称 | 资源方式 | 状态码 | 发送请求到服务器 |
---|---|---|---|
强缓存 | 从缓存中获取 | 200 (from cache) | 否,直接从缓存取 |
协商缓存 | 从缓存中获取 | 304 (not modified) | 是,通过服务器来告知缓存是否可用 |
强缓存(本地缓存)
- expire(有效期)
- 设置一个缓存过期的时间(值为GMT时间),具体到年月日秒,在这个时间内,则直接使用缓存数据
- 浏览器时间和服务器时间不同步
- 缓存过期后,不管文件有木有变化,服务器都会再次读取文件返回浏览器
- http1.0的东西,现在默认是1.1了,它的作用基本忽略
- cache-control:
- max-age:max-age=n秒,告诉客户端n秒后失效,n秒内都是使用本地缓存
- no-cache:不使用本地缓存,走协商缓存
- no-store:禁止浏览器缓存数据
- public:可以别所有用户缓存,内容可被缓存到到客户代理服务器
- private:内容仅能被缓存到客户端本地
如果 cache-control 和 expires 同时存在的话,cache-control 优先级高于 expires
协商缓存
协商缓存是有服务器来确定缓存资源是否可用
- 响应头 上配置 last-modified 或者 Etag
- 请求头 上配置 if-modified-since 或者 if-none-match
Last-Modified / If-Modified-Since
浏览器第一次 请求服务器资源,服务器返回资源,并且在
响应头 respone header
加上last-modified
的 header,这个表示资源在服务器上最后修改的时间浏览器再次 请求服务器资源,
请求头 request header
添加If-Modified-Since
的 header, 这个 header 的值是上一次请求返回的last-modified
的值服务器再次收到资源请求时候,根据 if-modified-since 和 资源在服务器上最后的修改时间判断 资源是否有变化。
- 没有变化 返回 304 not modified 的同时,返回响应头的 last-modified 不会改变
- 有变化就正常返回资源
浏览器接收到 304 的响应,就会从缓存中加载资源
如果协商缓存没有命中,浏览器直接从服务器加载资源时候,last-modified 会被重新更新
Etag / If-None-Match
这两个值是有服务器生成的每个资源的唯一标示字符串,资源有变化这个值就会改变
判断过程和 Last-Modified / If-Modified-Since 类似
与 Last-Modified 不同是 服务器返回的 304 not modified 响应时,由于 ETag 重新生成过, 响应头(response header) 也会把 ETag 返回,即使这个 ETag 更之前的没有变化
既生 Last-Modified 何生 Etag
Etag 主要是为了解决几个 last-modified 比较难解决的问题
一些资源也许会周期性的修改,但是他的内容并不改变(仅仅改变的是修改时间),这时候我们并不希望客户端认为这个文件被修改来,而重新 get
某些文件修改频繁,比如在秒一下的时间进行修改,(比如 1s 内修改来N次),if-modified-since 能检查到颗粒度是 s(秒)级的, 这种修改无法判断(或者说 UNIX记录MTIME只能精确到秒)
某些服务器不能精确到文件的最后修改时间
这时候 利用 Etag 能够更加准确的控制缓存,因为 Etag 是服务器自动生成或者开发者生成,对应资源在服务器端的唯一标示符
last-modified 和 Etag 可以一起是使用,服务器会优先验证 ETag,一致的情况下,才会继续对比 last-modified,最后决定是否返回 304
用户行为对缓存的影响
用户操作 | Expires / Cache-Control | Last-Modified / Etag |
---|---|---|
地址栏回车 | 有效 | 有效 |
页面链接跳转 | 有效 | 有效 |
新开窗口 | 有效 | 有效 |
前进后退 | 有效 | 有效 |
F5 刷新 | 有效 | 有效 |
Ctrl + F5 刷新 | 有效 | 有效 |
http 状态码 todo
- 2XX:成功状态码
- 200:服务器接收并处理成功
- 3XX:重定向
- 301:请求的资源被永久重定向
- 304:服务器回应客户端请求,告诉客户端本地缓存可用(协商缓存)
- 4XX:客户端错误
- 400:客户端请求语法错误(请求参数错误)
- 401:请求未授权,需要认证用户的身份
- 403:没有权限访问
- 404:访问的资源不存在
- 5XX:服务端错误
- 500:服务器内部错误
- 502(错误网关): 服务器作为网关或代理,从上游服务器收到无效响应
- 503:服务器端暂时无法处理请求(可能是过载或维护)
http、https 区别
HTTPS是HTTP协议的安全版本,HTTP协议的数据传输是明文的,是不安全的,HTTPS使用了SSL/TLS协议进行了加密处理,相对更安全
HTTP 和 HTTPS 使用连接方式不同,默认端口也不一样,HTTP是80,HTTPS是443
HTTPS 由于需要设计加密以及多次握手,性能方面不如 HTTP
HTTPS需要SSL,SSL 证书需要钱,功能越强大的证书费用越高
http:IP => TCP => HTTP(应用层)
https:IP => TCP => SSL => HTTP(应用层)
https 请求过程(ssl握手,加密过程)
- 客户端通过 URL 访问服务器建立 SSL 连接
- 服务器返回证书信息,客户端拿到公钥(证书中有公钥)
- 客户端和服务器协商 SSL 连接安全等级,也就是信息加密等级
- 客户端根据加密等级,建立会话密钥,然后利用获取的公钥对会话密钥进行加密,传送到服务器
- 服务器利用自己的私钥解密会话密钥
- 通过会话密钥加密进行通信
https 的缺点
- https 协议多次握手,导致页面加载时间过程
- https 链接缓存不如 http 高效,会增加数据开销和功耗
- 申请 SSL 证书需要钱,功能越强大证书费用越高
http 安全
XSS 跨站脚本攻击
恶意将代码注入到客户端攻击
攻击模式:
- 基于 DOM:恶意修改页面的 dom 结构,是纯粹的客户端攻击
- 存储型:例如写文章的平台,用户恶意写了一段js代码,保存文章,那么以后打开这篇文章的人都会遭到恶意代码的攻击
- 反射型:诱导用户点击恶意连接,用户点击后注入恶意脚本到客户端
预防:
- 给 cookie 设置
httpOnly
,禁止 js 脚本访问 cookie - 输入检查,不要相信用户输入的内容,对输入的内容进行必要的过滤、转义,例如vue源码里面 decodingMap 对输入内容转换,转义
- 输出检查,客户端拿到数据时候,有些渲染也要进行必要过滤、转义,vue 的 v-html,
- 给 cookie 设置
CSRF 跨站请求伪造
一种劫持受信任用户向服务器发送非预期请求的方式
通常情况 CSRF 攻击是借助受害者的 cookie 骗取服务器的信任来进行一些操作
- 预防:
- 服务端添加 Referer 判断
- token 验证,服务器生成token,前端请求的时候添加token,服务器校验token 是否正确
浏览器输入后回车的事情
- DNS 解析 url 对应的 ip
- 根据 ip 建立 TCP 连接(三次握手)
- 客户端发送 HTTP 请求
- 服务端处理请求,浏览器接受 http 响应
- 关闭 tcp 连接(四次挥手)
- 浏览器渲染页面,创建渲染树
渲染页面的过程以及遇到的问题
流程:
- 浏览器从上到下解析 html 文档,创建 dom 树
- 解析 css 生成 cssom (css 规则树)
- 解析完成后,浏览器会根据 dom 树和 css 规则树来构造渲染树(Render Tree)
- 根据渲染树的节点,布局到屏幕的正确的位置
- 遍历渲染树所有节点,绘制页面
浏览器在创建 dom 树过程:
遇到 css 的时候:会异步下载,生成异步的 css 规则树,不会堵塞 dom 树的出构建,但是会影响渲染树的最终生成, 因为渲染树有 dom 树和 css 规则树组成
遇到 js的时候:dom 树构建会停止,会先去加载和执行 js 代码,会中断构建 dom 树, 如果这时候 js 操作页面样式,还有可能造成,重绘或回流
这时候产生的优化问题:
css 优化:首屏页面 css 独立出来,放到 style 里面 内行加载
JS 优化:在页面的最下面引入 js,或者使用 defer 属性,这样页面在渲染会在渲染完成后加载
- async:异步加载,下载过程中不会影响到 html 的解析,但是下载完成后会立即执行,对堵塞 html 解析
- defer:异步加载,下载过程中不会影响到 html 的解析,会在所有的元素解析完成后,DOMContentLoaded 事件之前触发完成
tcp 的三次握手
三次过程:
- 客户端:你能收我消息么?
- 服务端:可以的,你能接收到我的回复吗?
- 客户端:可以的,那我们开始聊正事把
- 为啥是3次:
- 三次是最少的安全次数,两次不安全,四次浪费资源。
- 避免历史链接,确定客户端发的请求是这次通讯的人
- 为啥不是4次:
- 四次浪费资源
tcp 协议 四次挥手
TCP是全双工信道,何为全双工就是客户端与服务端建立两条通道:
- 通道1:客户端的输出链接服务端的输入
- 通道2:客户端的输入链接服务端的输出
两个通道可以同时工作:客户端向服务端发送信号的同时服务端也可以向客户端发送信号。
关闭通道:
- 客户端:我要关闭通道了
- 服务端:好的你关闭,我这边也要关闭通道了
- 服务端:我也要关闭通道了
- 客户端:好的,你关闭吧,我也吧这个通道关闭了
为什么不能是两次
- 无法确认服务端是否能到断开消息,还有服务端可能还有消息未发送完
为什么不能是三次
- 三次情况服务端接收到断开消息,向客户端发送确认接受消息,客户端未给最后确认断开的回复。