Http协议的组成
- 我们可以通过抓包工具抓一个请求, 然后就可以看到两部分信息, 一是客户端请求信息, 二是服务端响应信息.
- request请求信息:
- 请求行
- 三部分组成: 方法 URI/URL 协议版本
POST https://www.baidu.com HTTP/1.1
- 三部分组成: 方法 URI/URL 协议版本
- 请求头
- 紧挨请求行之后的部分, 用来说明服务器要使用的附加信息
- 主体
- 与请求头以空行分隔, 可以添加任意其他数据.
- 请求行
- response响应信息
- 状态行
- 三部分组成: 协议版本号 响应状态码 状态码消息
HTTP/1.1 200 OK
- 三部分组成: 协议版本号 响应状态码 状态码消息
- 消息报头
- 用来说明客户端要使用的一些附加信息
- 响应正文
- 服务器返回给客户端的文本信息.
- 状态行
- URL和URI
- URL: 用于描述一个网络上的资源
格式 指定协议类型 host: 主机域名 port: 端口号(浏览器访问域名默认80) path: 资源路径 query-string: 查询字符串 如, https://i.cnblogs.com/posts/edit?id=1002
- URI: 每个web服务器资源都有一个名字, 这样客户端就可以根据这个名字, 来找到对应的资源, 这个资源称之为(统一资源标识符)
- 总的来说, URI是一个用字符串来表示互联网上的某个资源, 而URL表示资源的地点(互联网所在位置)
- URL: 用于描述一个网络上的资源
- 方法有POST, GET, DELETE, PUT, OPTION, HEAD等
- GET(查询): 向特定的资源发出请求. 它本质就是发送一个请求来取得服务器上的某一资源.
- POST(创建): 向指定资源提交数据进行处理请求
- PUT(更新): 向指定资源位置上传其最新内容
- DELETE(删除): 请求服务器删除Request-URL所标识的资源
- OPTION: 返回服务器针对特定资源所支持的HTTP请求方法
- HEAD: 向服务器索与GET请求相一致的响应, 只不过响应体将不会被返回.
HTTP的三个版本
该部分参考于: https://juejin.im/post/5b0b99f16fb9a00a0d4b64cd
- HTTP1.0
- 短连接: 每个请求建立一个TCP连接, 请求完成过后立马断开连接.
- 短连接导致的问题
- 连接无法复用: 导致每次请求都经历三次握手和慢启动, 效率极低.
- 导致带宽无法被充分利用, 以及后续健康请求被阻塞.
- HTTP1.1
- keepalive连接: 允许HTTP设备在事务处理结束后将TCP连接保持在打开状态, 以便未来的HTTP请求重用现在的连接, 直到客户端或服务器端决定将其关闭.
- HTTP1.0中使用长连接要加: Connection: Keep-Alive.
- 而HTTP1.1中默认使用长连接, 除非Connection: close.
- chunked编码传输: 该编码将实体分块传送并逐块标明长度, 直到长度为0块表示传输结束. 这样在实体长度未知时很有用.
- 字节范围请求: HTTP1.1支持传送内容的一部分. 比方说, 当客户端已经有内容的一部分, 为了节省带宽, 可以只向服务器请求一部分. 该功能通过在请求消息中引入了range头域来实现, 它允许只请求资源的某个部分. 在响应消息中Content-Range头域声明了返回的这部分对象的偏移值和长度, 如果服务器相应地返回了对象所请求范围的内容, 则响应码206(Partial Content)
- keepalive连接: 允许HTTP设备在事务处理结束后将TCP连接保持在打开状态, 以便未来的HTTP请求重用现在的连接, 直到客户端或服务器端决定将其关闭.
- HTTP2.0
- 最大的特点: 不会改动HTTP的语义, HTTP 方法, 状态码, URI及首部字段等, 这些核心概念上一如往常, 却能致力于突破上一代标准的性能限制, 改进传输性能, 实现低延迟和高吞吐量.
- 之所以叫2.0, 是在于新增的二进制分帧层. 在二进制分帧层上, HTTP 2.0会将所有传输的信息分割为更小的消息和帧, 并对它们采用二进制格式的编码. 其中HTTP1.x的首部信息会被封装到Headers帧, 而我们的request body则封装到Data帧里面.
- HTTP 2.0通信都在一个连接上完成, 这个连接可以承载任意数量的双向数据流. 相应地, 每个数据流以消息的形式发送, 而消息由一或多个帧组成, 这些帧可以乱序发送, 然后再根据每个帧首部的流标识符重新组装.
- 随时复位: HTTP1.1一个缺点是当HTTP信息有一定长度大小数据传输时, 你不能方便地随时停止它, 中断TCP连接的代价是昂贵的. 使用HTTP2的RST_STREAM将能方便停止一个信息传输, 启动新的信息, 在不中断连接的情况下提高带宽利用效率.
HTTP协议的特点
- HTTP是无状态的
- 也就是说HTTP协议本身不会对请求和响应之间的通信状态做保存.
- Cookie机制能够实现有状态.
- 缺陷
- 通信过程使用明文, 内容可能被窃听.
- 不能验证通信双方的身份.
- 无法验证报文的完整性, 报文内容可能被篡改.
- 因此, 提出使用https来维护安全.
HTTPS基础
- 明文: 未被加密过的原始数据.
- 密文: 明文被某种加密算法加密后, 会变成密文.
- 密钥: 密钥是一种参数, 它是在明文转换为密文或将密文转换为明文的算法中输入的参数.
- 对称加密
- 明文 + 加密算法 + 私钥 -> 密文
- 密文 + 解密算法 + 私钥 -> 明文
- 这里私钥用的是同一把, 因为加密算法公开, 所以私钥被泄露, 则密文很容易被破解.
- 非对称加密: 公私钥结合
- 被公钥加密的密文只能通过私钥解密
- 明文 + 加密算法 + 公钥 -> 密文. 密文 + 解密算法 + 私钥 -> 明文.
- 被私钥加密的密文只能通过公钥解密
- 明文 + 加密算法 + 私钥 -> 密文. 密文 + 解密算法 + 公钥 -> 明文.
- 被公钥加密的密文只能通过私钥解密
HTTPS的原理
- HTTPS协议 = HTTP协议 + SSL/TLS协议, 即在HTTP传输时, 用到SSL/TLS对数据加密.
- 客户端发起请求
- 三次握手, 建立TCP连接
- 发送支持的协议版本(TLS/SSL)
- 客户端生成随机数: client.random(后续用于生成对话密钥)
- 发送客户端支持的加密算法
- sessionid, 用于保持同一个对话(若费尽周折建立了https连接, 刚建完就中断, 太亏了)
- 服务端收到请求, 然后响应
- 确认加密通道协议版本.
- 服务端生成的随机数server.random, 后续用于生成“对话密钥”.
- 确认使用的加密算法, 用于对后续的握手消息进行签名防止篡改.
- 响应服务器证书(CA机构颁发的)
- 客户端收到证书后进行验证
- 验证证书是不是CA签发的.
- 验证证书时, 浏览器会调用系统的证书管理器接口对证书路径中的所有证书一级一级的验证. 只有所有证书可信, 才算可信.
- 服务端返回的证书中包含有效期, 通过失效日期来验证证书是否过期.
- 验证证书是否被吊销了.
- CA机构在签发证书时, 都会使用自己私钥对证书签名.
- 证书里的签名算法字段sha256RSA表示CA机构使用sha256
对证书进行摘要, 然后使用RSA算法对摘要进行私钥签名, 而
我们也知道RSA算法中, 使用私钥签名之后, 只有公钥才能进
行验签.
- 证书里的签名算法字段sha256RSA表示CA机构使用sha256
- 浏览器使用内置在操作系统上的CA机构的公钥对服务器的证书进行验签, 确定这个证书是不是由正规的机构颁发, 验签之后得知CA机构使用sha256进行证书摘要, 然后客户端再使用sha256 对证书内容进行一次摘要, 如果得到的值和服务端返回的证书验签之后的摘要相同, 表示证书没被修改.
- 验证通过后, 会显示绿色的安全字样.
- 客户端生成随机数pre-master-secret, 它会根据之前的client.random+server.random+pre-master-secret生成对话密钥然后使用证书中的公钥进行加密. 同时利用前面协商好的加密算法, 将握手消息取hash, 然后用(握手消息+握手消息hash值)随机数加密后传递给服务端.
- 验证证书是不是CA签发的.
- 服务器接收消息
- 服务器端收到客户端的加密数据后, 用自己的私钥对密文进行解密, 然后得到client.random/server.random/pre-master-secret, 再用随机数密码解密握手消息和其hash值, 并与传过来的hash值对比.
- 然后用随机密码加密一段握手消息(握手消息+握手消息hash值)给客户端.
- 客户端接收消息
- 客户端用随机数密码解密并计算握手消息的HASH, 如果与服务端发来的HASH一致, 此时握手过程结束.
- 之后所有的通信数据由之前交互过程中生成的client.random/server.random/pre-master-secret算出sessionKey, 作为后续交互过程中的对称密钥.