HTTP
超文本传输协议
请求报文
我们来看一下请求报文的格式, 首先是请求行, 请求行包括方法, URL, 协议文本, 方法常见的有 GET/POST,URL 就是我们的请求地址, 协议文本一般是 HTTP1.1 版本
然后再看一下请求头, 头部字段都是以 key:value 的形式组合在一起的, 由多个首部字段名构成首部字段区域
之后是我们的实体主体, 一般在 GET 请求中没有实体主体, 而在 POST 请求中一般会带有实体主体
响应报文
首先是版本, 然后是状态码, 还有状态码的描述, 我们称之为短语, 然后下面跟请求报文一致, 由此组成响应报文
HTTP 的请求方式
- GET
- POST
- HEAD
- PUT
- DELETE
- OPTIONS
GET 和 POST 方式的区别
一般大家都知道的是:
GET 请求参数是以? 分割拼接到 URL 后面的, POST 请求参数实在 Body 里面的
GET 参数长度限制 2048 个字符, POST 一般没有该限制
GET 请求不太安全, POST 请求比较安全
但是从语义的角度来比较的话, 是这样的:
GET: 获取资源, 是安全的, 幂等的, 可缓存的
POST: 处理资源, 是非安全的, 非幂等的, 不可缓存的
对应的解释
1, 安全性: 不应该引起 Server 端的任何状态变化, 比如说我们用 GET 请求多次去 Server 端去获取数据, 不会引起 Server 的一个状态变化, 安全性的请求包括: GET,HEAD,OPTIONS
2, 幂等性: 同一个请求方法执行多次和执行一次的效果完全相同, 比如说我们用 GET 请求多次去 Server 端去获取数据, 执行的效果是完全相同的, 这里需要注意的是执行的效果, 幂等性的请求包括: GET,PUT,DELETE
3, 可缓存性: 请求是否可缓存, 我们一般在发起一个 HTTP 请求的过程中, 传递的链路我们是不确定的, 虽然说实在一条 TCP 连接上, 但是网络路径在接触或者通过网关包括一些代理到达我们的 Server 端, 在这上面会涉及到方方面面的内容, 往往对于一些代理服务器会有缓存, 而这种缓存性是官方的一种规范, 即可以遵守也可以不遵守, 大多数情况会遵守, 所以在 GET 请求会有相对应的缓存, 可缓存性的请求包括: GET,HEAD
状态码
1XX: 通知
2XX: 成功
3XX: 重定向
4XX: 客户端错误
5XX: 服务端错误
连接建立流程
三次握手
首先是客户端发送一个 SYN 的请求报文给服务端, 请求建立连接
当服务端收到报文后, 服务端会返回给客户端一个同步 ACK 的报文
当客户端收到报文后, 会返回给服务端一个 ACK 报文, 完成三次握手
四次挥手
如果是客户端发起主动断开, 客户端会发送一个 FIN 终止报文给服务端
服务端会返回给客户端一个 ACK 确认报文, 这时客户端与服务端的连接就断开了, 但是服务端到客户端这个方向, 可能还会传递数据, 在一个合适时机, 服务端会向客户端请求断开连接
服务端想要断开连接的时候, 会向客户端发送 FIN 终止报文
然后客户端会回给服务端一个确认报文, 此时完成服务端与客户端的连接断开
HTTP 的特点
无连接, 补偿方案为 HTTP 的持久连接
无状态, 补偿方案为 Cookie/Session
HTTPS 与网络安全
HTTPS = HTTP + SSL/TLS
HTTPS 就是在原有 HTTP 基础上, 在应用层下面, 传输层上面插入了一个 SSL/TLS 协议中间层, 为我们实现一个安全的网络机制, 也就是说 HTTPS 是安全的 HTTP
HTTPS 连接建立流程
首先由客户端向服务端发送一个报文, 这个报文包括三部分, 一个是客户端支持的 TLS 版本, 客户端支持的加密算法, 以及一个随机数 C
然后服务端返回一个握手报文消息, 包括一个商定的加密算法, 随机数 S 还有一个服务端的证书
客户端收到这条报文后, 首先会验证证书, 之后会组装会话秘钥, 这个秘钥主要通过前面的随机数 C 和随机数 S 以及一个预主秘钥进行会话秘钥的组装
然后客户端会通过服务端的公钥对预主秘钥进行加密传输, 之后服务端通过私钥解密得到预主秘钥, 最后服务端会通过前面的随机数 C, 随机数 S 以及解密得到的预主秘钥组装会话秘钥
之后再由客户端向服务端发送一个加密的握手消息, 服务端发送一个加密的握手消息, 来验证是否加密完成
TCP/UDP
传输层协议
TCP: 传输控制协议
UDP: 用户数据报协议
UDP(用户数据报协议)
特点:
1, 无连接
2, 尽最大努力交付
3, 面向报文, 既不合并, 也不拆分
功能包括:
1, 复用
2, 分用
3, 差错检测
TCP(传输控制协议)
特点:
1, 面向连接
2, 可靠传输 (无差错, 不丢失, 不重复, 按序到达)
3, 面向字节流
4, 流量控制
5, 拥塞控制
DNS 解析
域名到 IP 地址的映射, DNS 解析请求是采用 UDP 数据报, 且明文
DNS 解析查询方式
递归查询 (一层一层的查询)
迭代查询 (返回结果找对应查询)
DNS 劫持问题
当客户端发送域名去 DNS 服务器去查询时, 由于是 UDP 数据包并且明文, 就会被窃听, 这时如果有一个钓鱼服务器劫持了这次查询, 返回给你一个错误的 IP, 这时你就会访问到一个错误的网页
这里还需要注意一个点: 就是 DNS 劫持和 HTTP 是完全没有关系的, 因为 DNS 解析是发生在 HTTP 建立连接之前, 并且 DNS 解析请求使用的事 UDP 数据报, 端口号 53
那么如何解决 DNS 劫持问题呢?
httpDNS:DNS 解析请求使用的事 UDP 数据报, 端口号 53, 解决方案是使用 HTTP 协议向 DNS 服务器的 80 端口进行请求, 不会产生正常的 DNS 解析, 也就不会出现 DNS 的劫持问题
长连接: 在客户端和服务端之间建立一个长连服务, 也就是一个代理服务器, 在客户端和代理服务器之前建立长连通道, 然后再代理服务器和服务端之间通过内网专线进行内网 DNS 解析, 然后进行请求
DNS 解析转发问题
简单一句话, 就是我们客户端发送请求时, 我们的 DNS 服务器可能为了节省资源等原因, 会转发给其他的 DNS 服务器, 会出现跨网访问, 可能会慢一点
Session/Cookie
HTTP 协议无状态特点的补偿
Cookie
主要是用来记录用户状态, 区分用户; 状态保存在客户端, 客户端发送的 Cookie 在 http 请求报文的 Cookie 首部字段中, 服务端设置 http 响应报文的 Set-Cookie 首部字段
修改 Cookie
新 Cookie 覆盖旧 Cookie
覆盖规则: name,path,domain 等需要与原 Cookie 保持一致
删除 Cookie
新 Cookie 覆盖旧 Cookie
覆盖规则: name,path,domain 等需要与原 Cookie 保持一致
设置 Cookie 的 expires = 过去的一个时间点, 或者 maxAge = 0
怎样保证 Cookie 的安全性
对 Cookie 进行加密处理
只在 https 上携带 Cookie
设置 Cookie 为 httpOnly, 防止跨站脚本攻击
Session
也是用来记录用户状态, 区分用户; 状态保存在服务端 Session 需要依赖于 Cookie 机制
来源: https://juejin.im/post/5c25f083e51d457454699ed6