目录
[1. HTTP 协议格式](#1. HTTP 协议格式)
1) URL URL)
2) 请求方法 请求方法)
3) 认识 Header 认识 Header)
4) 响应状态码 响应状态码)
[2. HTTPS](#2. HTTPS)
1) 加密和解密 加密和解密)
2) HTTPS 的工作过程 HTTPS 的工作过程)
a) 先引入对称加密 先引入对称加密)
b) 引入非对称加密 引入非对称加密)
c) 引入证书 引入证书)
1. HTTP 协议格式
HTTP (全称 "超文本传输协议") 是一种应用非常广泛的应用层协议。
目前 HTTP 最新版本是 HTTP/3.0,但是现在大规模使用的版本是 HTTP/1.1 。
使用 HTTP 协议的场景:
浏览器打开网站 (基本上)
手机 APP 访问对应的服务器 (大概率)
所以基本上 HTTP 覆盖了我们日常上网的绝大部分场景。
而学习 HTTP 协议,就要重点学习 HTTP 协议的报文格式。
HTTP 协议的报文格式要分两个来看待,请求和响应。
HTTP 协议是一种 "一问一答" 结构模型的协议,请求和响应的协议格式,是有差别的。
可以使用 Fiddler 来抓包(抓包就是把网卡上经过的数据给获取到然后显示出来),来查看 HTTP 请求和响应格式。
点击其中一个包后,右侧会显示这个包的详情。
新安装的 fiddler 需要手动开启 HTTPS 功能,并且安装证书,否则只能抓 HTTP,当前互联网环境下,HTTPS 为主,纯 HTTP 已经很少见了。
Fiddler 本质是一个 "代理",可能会和其他的代理软件产生冲突。
举个例子:
除了 fiddler 以外,有些程序也是代理(比如加速器,vpn....),代理程序之间,是可能会冲突的,如果使用 fiddler 抓不了包,就可以看看是不是之前开了代理没关,把代理关了再试试。
如果觉得当前 fiddler 抓到的包太多了,那就可以随便选中一个包,按 ctrl + A 选中全部,再按 delete 删除。
HTTP 协议是一个文本格式的协议,用记事本打开不会乱码,协议里的内容都是字符串。
TCP/UDP/IP 都是二进制格式的协议。
HTTP 响应也是文本的,直接查看,往往能看到二进制的数据(压缩后的),
HTTP 响应经常会被压缩,压缩之后,体积变小,传输的时候,节省网络带宽。
解压缩之后,可以看到响应的数据是个 html,浏览器上显示的网页,就是 html,往往都是浏览器请求对应的服务器,从服务器这里拿到的页面 (html) 数据。
HTTP 请求包含四个部分:
1. 首行
2. 请求头
3. 空行
4. 正文
比如:
HTTP 响应分为四个部分:
1. 首行
2. 响应头
3. 空行
4. 正文
比如:
虽说是有差别,但是大同小异。
1) URL
URL 是计算机中一个非常重要的概念,它描述了一个资源在网上所属的位置。
如图:
关于 url,举个例子,比如说我不当大学生啦,我直接在陕科大六餐厅盘个窗口,19 号窗口,我去那里卖冰糖葫芦,http://陕科大六餐厅:18号窗口/冰糖葫芦/草莓冰糖葫芦?糖纸=裹起来&包装袋=包起来。
#ch1 是片段标识符,有的网页比较长,就可以分成多个 "片段",通过片段标识符,就可以完成页面内部的跳转,一般技术文档用的比较多。
对于 query string 来说,如果 value 部分包含一些特殊符号的话,就需要进行 urlencode 操作。
urlencode 本质上是一种转义字符。
比如说 + ? : / ...... 这些符号在 url 中都已经有特殊用途了,如果 url 中包含的话,就可能会使浏览器/http服务器,对于 url 的解析出现 bug,导致请求无法正常进行,中文汉字也需要进行转义。
2) 请求方法
GET 请求,通常会把要传输给服务器的数据,加到 url 的 query string 中,
而 POST 请求,通常会把要传输给服务器的数据,加到 body 里。
是习惯用法,不是硬性规定,也可以不遵守。
HTTP 的方法有:
GET
POSTPUT
HEAD
DELETE
OPTIONS
TRACE
CONNECT
LINK
UNLINK
**以上方法,除了 GET 和 POST 都不是很常见,**天下 HTTP 请求如果是十斗,GET 独占八斗,POST 占一斗,剩下的其他的请求,共分一斗。
这些 HTTP 请求,最初的初心,其实是为了表示不同的语义,但是在实际的使用过程中,大家已经把初心忘了,所以 HTTP 的各种请求,目前来说已经不一定完全遵守自己的初心了,实际上程序员如何使用,还是更加随意的。
GET 和 POST 有什么区别?
本质上没有任何区别 (双方可以替换对方的场景),但是在使用习惯上有些差别。
1. 在向服务器传输数据时, GET 一般把数据放在 url 的 query string 中,POST 则把数据放在正文里。
2. 虽然 HTTP 请求方法的语义是比较混乱的,但是 GET 和 POST 还是比较明确的,GET 一般用来获取数据,POST 一般用来提交数据(登录 + 上传)。
3) 认识 Header
Header 里的键值对是很多的,所以主要是挑几个重要的来介绍。
1. Host
描述了服务器所在的 ip 和端口号。
这个信息在 url 中也是存在的,在使用代理的情况下,Host 的内容可能和 url 中的内容是不同的
2. Content-Length 和 Content-Type
Content-Length 表示 body 中数据的长度。
Content-Type 表示 body 中数据的格式。
请求里有 body,才会有 Content-Length 和 Content-Type 这两个属性。
一般 GET 请求就没有,POST 请求有 body。
TCP 涉及到粘包问题,HTTP 在传输层就是基于 TCP 的,使用同一个 TCP 连接,传输多个 HTTP 数据包,这些 HTTP 数据包就会在 TCP 的接收缓冲区紧紧挨在一起,接收方解析的时候,就需要明晰 HTTP 数据包之间的边界,如果是 GET 这种没有 body 的请求,就使用空行(分隔符),如果是 POST 这种有 body 的请求,就可以使用空行和 Content-Length。
Content-Type,body 中的格式,选择的方式是非常多的:
请求:
1) json
2) form 表单的格式(相当于是把 GET 的 query string 搬到 body 中)
3) form-data 的格式(上传文件的时候,会涉及到,也不一定是 form-data,也可能是 form 表单)
响应:
1) html
2) css
3) js
4) json
5) 图片
- 响应的 body 的格式还有很多.....
后续给服务器提交请求,不同的 Content-Type,服务器处理数据的逻辑是不同的,服务器返回数据给浏览器,也需要设置合适的 Content-Type,浏览器也会根据不同的 Content-Type 做出不同的处理。
3. User-Agent (简称 UA)
UA 描述了你使用什么设备上网。
现在 UA 主要是用来区分是 PC 端还是移动端,做这样的区分,一般只是为了统计,而不会返回不同版本的页面,前端开发有个 "响应式网页" 编程技术,同一个 html 可以兼容不同的设备。
4. Referer
描述了当前页面是从哪个页面跳转来的。
如果是直接在地址栏输入 url (或者点击收藏夹中的按钮) 都是没有 Referer 的。
现在,网络上都是 HTTPS 为主了,很少见到 HTTP。
5. Cookie
Cookie 是浏览器在本地存储数据的一种机制。
Cookie 往往是存储的从浏览器返回的数据(也可以是页面自己生成的)
Cookie 存储到浏览器所在主机的硬盘上,并且是按照 域名 为维度存储的(每个域名下可以存自己的 Cookie,彼此之间不影响)
Cookie 是按照键值对的方式来组织的,这里的键值对都是程序员自定义的(和 query string 差不多)。
后续再请求这个服务器的时候,Cookie 中的内容就会自动代入到请求中,一同发给服务器,服务器根据 Cookie 中的内容做一些逻辑上的处理。
比如这个,就是 Cookie,这些内容都是程序员自定义的
键值对之间使用 ; 分割,键和值之间使用 = 分割,这些内容就是浏览器存储到本地的 Cookie,后续在请求服务器的时候,会把这些内容代入到请求中,传给服务器。
4) 响应状态码
响应状态码表示了这次请求对应的响应,是什么样的状态(成功,失败,其他的情况,对应的原因是什么)
2xx 表示成功,3xx 表示重定向,4xx 表示请求错误,5xx 表示服务器错误
重点需要关注的有:200,301,302,403,404,500
200(OK):成功
301 (Moved Permanently):永久重定向。 302 (Found):临时重定向
重定向:请求中访问的是 A 地址,响应返回了一个重定向报文,告诉你应该访问 B 地址,重定向响应的报文中,会带有 Location 字段描述出当前要跳转到哪个新的地址。
403 (Forbidden):没权限访问. 404 (Not Found):资源不存在
出现 4xx 的话,一般是你 url 写错了
500 (Internal Server Error):服务器出错
出现 5xx 的话,一般是你服务器代码写错了,抛异常什么的。
如何构造 http 请求?
直接在浏览器地址栏输入 url,此时就构造了一个 GET 请求。
html 中,一些特殊的 html 标签(比如 img,a,link,script...),可能会触发 GET 请求
通过 form 表单来触发 GET/POST 请求
通过 ajax
还可以通过 postman
2. HTTPS
当前网络上,主要都是 HTTPS 了,很少能见到 HTTP。
实际上 HTTPS 也是基于 HTTP(前面介绍的 HTTP 的各个方面的内容,对于 HTTPS 同样适用)
只不过 HTTPS 是在 HTTP 的基础上,引入了 "加密" 机制。
引入 HTTPS 是为了防止你的数据被黑客篡改(尤其是反针对运营商劫持)。
比如说,去一些饭店、商场,你就想连人家的 wifi:
敏感数据,在网络上可千万不能明文传输,一定要加密。
1) 加密和解密
HTTPS 就是一个重要的保护措施,之所以能够安全,最关键的在于加密。
加密就是把明文(要传输的原始信息) 进行一系列的变换,转换成密文。
解密就是把密文再进行一系列的变换,转换成明文。
在加密和解密的过程中,往往需要一个或多个中间的数据,辅助进行这个过程,这样的数据,称为 "密钥"。
明文 + 密钥 => 密文
密文 + 密钥 => 明文
在密码学中,使用密钥加密,有两种主要方式:
1. 对称加密:加密和解密,使用的密钥是同一个密钥。
设密钥为 key,明文 + key = 密文,密文 + key = 明文
2. 非对称加密:有两个密钥(一对),一个称为公钥,一个称为私钥(公钥就是可以公开的,私钥就是被自己藏起来的)
一个用来加密,另一个就用来解密。
明文 + 公钥 => 密文 密文 + 私钥 = > 明文
或者
明文 + 私钥 = > 密文 密文 + 公钥 => 明文
就比如说商场的储物柜,投个硬币,就能拿到对应柜子里的钥匙,然后就可以把东西给放进柜子里,然后把柜子锁好,之后要取出里面的东西的话,就直接用钥匙开锁就行,这里的锁和钥匙是一对,锁就相当于公钥,钥匙就相当于私钥,你在柜子里放的东西就是明文,锁柜子就相当于加密,用钥匙解锁就是解密,加密和解密的前提是,锁和钥匙是一对。
2) HTTPS 的工作过程
HTTPS 就是针对 HTTP 的 header 和 body 进行加密。
a) 先引入对称加密
b) 引入非对称加密
此时就需要引入非对称加密,将密钥进行非对称加密就好了。
非对称加密,有一对钥匙,分别是公钥和私钥,使用其中一个加密,另一个就用来解密。
为什么使用了非对称加密,还要使用对称加密呢?直接用非对称加密来完成所有的业务数据的加密不就好了?
非对称加密/解密,运算成本是比较高的,运算速度也是比较低的。
对称加密,运算成本低,运算速度快。
所以使用非对称加密,就只在关键环境(传输密钥,一次性工作,体积也不大),成本就比较可控,后续要传输大量的数据,使用效率更高的对称加密,是更好的做法。
如果业务数据都使用非对称加密,那传输效率就会很低。
引入安全性,引入加密,势必会对传输效率产生影响,就会希望能够把这里的影响降到最低。
但是上述的 非对称加密 + 对称加密 的流程还存在一个严重的漏洞,如果黑客利用好这个漏洞,仍然可以获取到原始数据。
这个漏洞称为中间人攻击。
那该如何解决 中间人攻击 呢?
仔细想想,就能发现,问题的关键在于客户端无法分辨出 这个公钥是否是黑客伪造的,
所以就可以引入第三方被大家都信任的 "公正机构" 。
公正机构说这个公钥是真的,不是被伪造的,那我们就可以信任。
c) 引入证书
https 加密:
1. 通过对称密钥,来加密业务数据
2. 用非对称密钥,来加密对称密钥
3. 通过公正机构颁发的证书里的数字签名,来校验是否是服务器的原始公钥