网络原理 HTTP 和 HTTPS
目录
一 . HTTP 协议
二 . 抓包
三 . HTTP 请求 / 响应的基本格式
(1)HTTP请求的基本格式
(2)HTTP响应的基本格式
四 . HTTP 方法
GET 和 POST 的区别:
五 . 请求报头和响应报头
(1)HOST
(2)Content - Length 和 Content - Type
(3)User - Agent(简称 UA )
(4)Referer
(5)Cookie
六 . 状态码(status code)
七 . HTTPS
(1)密钥
(2)HTTPS 的基本工作流程
1 . 引入对称加密
2 . 传输对称密钥给服务器
3 . 引入非对称加密
4 . 中间人攻击
5 . 为了避免中间人攻击,引入证书系统
一 . HTTP 协议
HTTP 全称为超文本协议,是一种应用非常广泛的应用层协议。HTTP 诞生于 1991 年,目前已经发展成为最主流的一种应用层协议。
为什么 HTTP 被称为 “ 超文本 ” 呢?这是因为 HTTP 不仅能传输文本,还能传输图片、视频、音频文件以及其他各种数据。
HTTP 协议,是一种典型的 “ 一问一答模型 ” 协议。就是针对服务器与客户端之间的,客户端发一个请求,服务器返回一个响应。
二 . 抓包
借助抓包工具,我们可以观察到 HTTP 请求 / 响应的详细情况。
抓包就是把通过网卡上的数据获取到,并解析显示出来。
这一中间的抓包过程,也像个代理人一个,所以我们又将抓包程序这一过程称之为 “ 代理 ” 。
代理,又分为正向代理和反向代理:
三 . HTTP 请求 / 响应的基本格式
(1)HTTP请求的基本格式
1 . 首行
2 . 请求头(header)
若干键值对,从第二行开始的若干行,一直到空行结束。
3 . 空行
作为请求头的结束标记。
4 . 正文(body)
有的请求中有 body ,有的则没有。body 中是一个个加密过的键值对,通过 “ :” 分隔开。
(2)HTTP响应的基本格式
1 . 首行
首行的三个部分使用空格分隔,请求也是如此。
2 . 响应头(header)
每一行是一个键值对,不确定几行,以空行结尾,键和值之间使用 ;分隔。
键值对也是标准规定的,有的键值对只能出现在请求中,有的只能出现在响应中,有的则都可以。
3 . 空行
作为响应报头的结束标记。
4 . 正文
对于响应来说,正文通常是 HTML、CSS、JS、JSON、图片、音频、字体等等,体现了服务器给浏览器返回的数据。
四 . HTTP 方法
在我们HTTP中有很多很多方法,其中我们最最最常用的就是 “ GET ” 和 “ POST ” 。
大家小时候应该都学过一篇语文课文《世说新语》,其中有一篇写谢安的文章,谢安有个很有名得的曾侄子 —— 谢灵运,谢灵运有句名言典故:才高八斗。他说,魏晋以来,天下文采共十斗,曹子建独占八斗,我得一斗,自古至今其余人共分一斗。他这话其实吹牛了昂,看似夸曹植,实际夸自个呢,可能那天谢老爷子喝高了。
但这话放在我们的 HTTP 方法中就很恰当了,可以说,天下 HTTP 方法共十斗,GET 独占八斗,POST 得一斗,其余方法各分一斗。
GET 请求也就是从服务器中拿到某个请求数据,POST 就是向服务器发送一个请求数据。
有很多场景都会涉及到 GET :
(1)直接在浏览器输入一个 URL ,此时就会触发 GET 请求。
(2)HTML 页面中很多元素会进一步触发 GET 请求。
(3)JS 代码中也能够触发 GET 请求。
涉及到 POST 的场景:
(1)登录 / 注册的时候。
(2)上传文件的时候。
GET 和 POST 的区别:
首先,明确抛出结论:这两种方法,这两种方法其实没有本质区别(GET 能用的场景,换成 POST 也可以,同理,POST 能用的场景,换成 GET 也可以),但是有一定的区别:
(1)语义上的区别:GET 表示从服务器拿数据, POST 表示向服务器提交数据。(如果你想要使用 GET 提交数据,用 POST 拿数据也是可以的,但是这种做法不常见)
(2)传递数据的方式不同:GET 传递数据通常是通过 query string 把自定义数据提交给服务器。POST 在传递数据的时候,通常通过 body 把自定义数据提交给服务器。(同理,GET 也能加 body,给 POST 也能加 query string ,只是一般不这么做)
(3)GET 方法对应的请求,通常设计成 “ 幂等 ”的,POST 对应的请求对于 “ 幂等性 ” 则无要求。
(4)承接幂等性:GET 如果设计成幂等的,此时的 GET 的结果是可以被缓存的。POST 不设计成幂等性,POST 就不应该被缓存。
五 . 请求报头和响应报头
请求报头与响应报头其实质就是键值对,我们挑几个比较重要的来讲一讲。
(1)HOST
表示服务器主机的地址和端口。
(2)Content - Length 和 Content - Type
Content - Length 表示 body 中的数据长度,单位是字节。告诉我们,一个 HTTP 数据报到哪里就结束了( HTTP 基于 TCP ,TCP 面向字节流,存在粘包问题,如何解决粘包问题呢?在我上一期有讲到过,常用的有两种方法:指定分隔符,指定数据报长度)。
Content - Type 表示请求或响应的 body 中的数据格式。
如果一个请求 / 响应中没有 body ,也就没有这俩字段;如果有 body ,则必须要有这俩字段。Content - Length 和 Content - Type 在请求和响应中都可能存在。
(3)User - Agent(简称 UA )
在 UA 中主要包含两个信息:1 . 操作系统信息(版本);2 . 浏览器信息(版本),这两种信息表明你在使用怎样的设备上网。
UA 现在还有一个作用,用来做数据统计。这是我们日常开发的重要环节,因为很多方案的设计、执行并不是一个人一拍脑门就决定的,而是需要讨论,更需要一定的数据支撑,而我们通过 UA 可以统计很多的业务指标,然后根据统计结果来进一步的迭代改进产品。( UA 的统计主要用于区分 PC 端和移动端)
(4)Referer
Referer 就是描述了当前页面是从哪个页面跳转过来的。大家注意,Referer 这个东西,并不一定真的有,当我们直接在地址栏输入URL 或点击收藏夹跳转的网页,咱们就抓不到 Referer 的包。
大家注意,Referer 跟浏览器网页的回退操作并没有关系,这两者不相同。Referer 是在 HTTP 请求当中,发给服务器的,这个东西是给服务器使用的。而浏览器的回退,是浏览器自身的行为,与 HTTP 协议无关,浏览器给每个标签页都维护了一个 “ 栈 ” 这样的数据结构,回退相当于 “ 出栈 ” 。
上面说的统计数据,Referer 在统计数据这一块也有很大作用,例如我们同一个广告主会在多个平台通过多个渠道投放广告,我们在百度上点击会跳转到广告主的页面,在搜狗上点击,也会跳转到广告主页面,广告主在自己的网站这边,是可以很容易统计出一段时间内有多少访问量 / 点击量的,Referer 的主要作用就是用来区分,这些点击,哪些来自于百度,哪些来自于搜狗。因为广告是按照点击量进行付费嘛,为了以防有造假行为,百度会统计这个广告有多少点击量,而广告主自己也会统计,只有这两个统计的数据对上了,广告主才会付费。
(5)Cookie
Cookie 是浏览器本地持久化储存数据的一种机制,它是按照键值对的形式进行存储的,键值对之间用 “ ;” 进行分隔,键值对内用 “ = ” 进行分隔键和值。值得注意的是,这里面的键值对都是程序员自定义的,并且按照域名为维度分别进行储存。(每个网站有自己的 Cookie ,相互不影响)
上述 Cookie 中的这种键值对,看似是从浏览器通过请求发送给服务器的,实际上这些数据最初都是从服务器返回给浏览器,此处看到的这些数据,都相当于是在浏览器本地储存的。Cookie 是属于浏览器给网站提供的一种 “ 客户端储存数据 ” 的机制。对于网站来说,主要的数据都是在服务器这边储存的,也有些数据需要在浏览器这边存储,例如上次访问的时间,访问的网址,用户的基本身份信息等等。
为了安全,浏览器禁止网页直接访问用户的硬盘,这一条是在文件系统中直接规定死的,大家想一想,咱们要是想在夜深人静的时候,悄悄地打开一个学习网站学习学习,但是一打开,网页直接访问硬盘资料,将我们里面的数据删的一干二净,这是一件多么可怕的事情。但是浏览器并没有把这条路封死,还是开了个小口子,允许网页通过键值对的方式来储存数据(这样的数据其本质也是在硬盘上),具体这样的键值对是怎样存储到硬盘上的呢?这件事是浏览器封装好的,网页本身无法干涉,这就是我们的 Cookie 机制。
Cookie 从哪里来的呢?注意,首次访问某个网站,可能是不带 Cookie 的,在响应中就会有 Set - Cookie 字段(可能有多份,这是服务器这边的程序员根据需要,编写代码生成的)这样的 Header ,把一些键值对写回到浏览器这边,浏览器后续访问这个网站就会带有 Cookie 。
Cookie 要到哪里去呢?后续浏览器访问同一个服务器的时候,就会把之前储存的 Cookie 再带上,从而发送到服务器这边。这个时候有的小伙伴就可能会问了,既然是从服务器拿出来的,我们下次又放回服务器,这不是多此一举嘛,我们干嘛不直接一直放着呢?大家上学都有放过假吧,咱们放假是不是会把一些书本作业都装一些带回家(其实我以前装回去的书基本没动过,特别是上大学以后,手动狗头),咱们开学了又得带回学校。通过这一例子就说明什么?说明一个服务器,可能同时会给多个客户端提供服务,Cookie 中的数据,也是属于可能在客户端使用也可能在服务器使用。值得注意的是,Cookie 有一个充分的自定义空间,Cookie 的某个键值对,可能只是服务器用,可能只是客服端用,也可能两边都要用。
随着我们时代的变迁,互联网科技的发展,Cookie 也不是唯一一个能在浏览器这边储存数据的机制了,它可以说是最早的,但放在现在来说并不是唯一的。目前还有 Local storage(也是键值对)、Index db(类似于表这样的结构) 这些更新型的机制,也可以通过这样的机制来存储会话 ID 。
登录的信息验证,也不一定都是基于 session 这样的方式来存储了,也有一些其他的方式,比如目前业界比较流行的 jwt(把用户的信息就存储在客户端,但是会对其进行加密操作) 的这种方式。
六 . 状态码(status code)
HTTP 状态码主要分为五个大类,分别是:
1XX(临时响应,指示信息):表示临时响应并且请求已接收需要请求者继续执行操作的状态码:
2XX(响应成功): 表示动作被成功接收、理解和接受。
3XX(重定向):为了完成指定的动作,必须接受进一步处理。
4XX(客户端错误):请求包含错误语法或不能正确执行。
5XX(服务器错误):服务器不能正确执行一个正确的请求。
6XX状态码:
七 . HTTPS
我们随便打开一个网页可以发现,当前的网址都是 “ https ” 形式,为什么不是我们的 “ http ” 呢?这个 https 跟 http 有什么区别呢?这就涉及到 “ 运营商劫持 ” 。
我们先来了解一下什么是运营商:
运营商指的就是提供宽带服务的 ISP ,我国有三大运营商:中国电信、中国移动、中国联通,还有一些小运营商,比如长城宽带、歌华有线宽带。运营商为我们提供了最基础的网络服务,掌握着通往用户物理大门的钥匙。
什么是运营商劫持呢?
在以前的年代,由于大家对互联网知之甚少,一些运营商为了自己的利益,会给你的网页页面上加上各种页面里本来没有的元素,例如:广告、弹框等。而当年对于互联网的法律没有那么完备,所以一度导致这种 “ 运营商劫持 ” 的现象很猖獗,在十年前,这一现象是很普遍的。
怎样应对运营商劫持呢?
(1)全站 https ,能防一部分。
(2)加入防运营商劫持代码,能防大部分注入型劫持。
(3)记录 Log ,记录证据,向工信部投诉。
就算我们的网站不被运营商劫持,也有可能被黑客劫持,而被劫持的很大原因就是因为 HTTP 的明文传输,所以目前来说,解决这种被劫持最高效的方案就是:HTTPS 加密,进行密码传输。
(1)密钥
明文:需要传输的原始数据。
密文:把明文进行加密之后得到一个让别人不能理解的数据。
加密:明文 —> 密文。
解密:密文 —> 明文。
密钥:进行加密和解密的重要数据 / 辅助工具。
如图,该奏折中的文字就相当于密文,而挖了孔的封 面纸就相当于密钥。
对称加密:加密和解密共用一个密钥。
非对称加密:加密和解密分别用两个密钥,一个 “ 公钥(公开出来的密钥,谁都可以拿到)” ,一个 “ 私钥(私藏起来的密钥)” 。这两个没有固定的加密解密,使用其中一把密钥加密,就需要使用另一把进行解密。
(2)HTTPS 的基本工作流程
HTTPS 只是在 HTTP 的基础上引入了加密机制,其他部分完全一致。
1 . 引入对称加密
由于在客户端与服务器的交互过程中,一个服务器往往对应着多个客户端,所以我们的多个客户端必须得使用不同的密钥(要不然黑客只要自己创建一个客户端不就也知道密钥了嘛),因此我们就要求,让每个客户端在连上服务器的时候,自己生成一个随机的对称密钥。
2 . 传输对称密钥给服务器
按照这样的传输方式,看似可行,但是我们不管套多少层,依旧必须经过一次明文传输将密钥传给服务器,任然有可能被黑客截获到这个密钥。
3 . 引入非对称加密
通过非对称加密,对需要进行传输的对称密钥进行加密非对称加密的存在目的并不是为了取代对称加密,而是起到一小部分的 “ 辅助 ” 作用。主要的业务数据仍然是使用对称加密,但是需要使用非对称加密来加密传输的对称密钥。
为什么不完全使用非对称加密来加密数据呢?这其中最主要的原因就是涉及成本的问题,非对称加密的运算量开销比较大,非常消耗计算机性能。
4 . 中间人攻击
5 . 为了避免中间人攻击,引入证书系统
这个问题的关键是,能够让客户端识别出拿到的公钥是不是正确的,合理的,而不是伪造的公钥。那么我们如何证明公钥是合理的呢?此时就需要引入第三方证书机构。
如果你想搭建服务器,使用 HTTPS ,就需要在公证机构这里申请证书(电子的一串数据),申请的时候需要提交部分资料(如网站的域名,营业执照,备案号. . . . . )
然后公证机构就会生成一个 “ 电子证书 ” ,其内容主要包含如下几个字段:证书发布机构,证书有效期,公钥,证书所有者,签名 . . . . . 其中最重要的就是 “ 签名 ” ,它是保证证书合法的关键要点。
签名就是:证书中的各个字段综合在一起,计算校验和(原始数据相同,计算得到的校验和就相同,校验和不同,说明原始数据就不同)。计算完校验和之后,再对其进行非对称加密的操作。
公证机构自己生成一对公钥、私钥,私钥由公证机构自己保存,公钥则会分发给各种客户端。公证机构拿着自己的私钥对刚才的校验和进行加密,于是就得到了我们的数字签名。
服务器申请到证书之后,后续客户端从服务器拿公钥,就不只是拿公钥,而是拿整个证书。此时客户端就可以凭借证书中的数字签名,对证书的合法性进行验证。
客户端如何进行验证签名呢?
1 . 客户端先将证书中的各个字段再算一次检验和,得到 checksum1。
2 . 客户端使用公证机构的公钥,对数字签名进行解密,得到 checksum2。
3 . 对比 checksum1 == checksum2 ,如果相等,视为当前证书的每个字段就是和服务器这边发出来的一模一样,此时就可以认为其是合法证书。反之,若是不相等,就会被视为被不法分子篡改过了,此时浏览器网页往往就会弹出警告标志,提示用户,该网页不安全(大家访问一些学习网站的时候应该多多少少看见过哈,其实并不怎么样,无视风险访问哈哈哈)。
当客户端手里拿着公证机构的公钥,怎么验证这个公钥是不是正确的呢?它不是黑客伪造的呢?这个大可不必担心,因为这个公钥是操作系统内置的,并不是通过网络能获取的,一般的黑客,是几乎没有可能拿到这层信息的。
黑客可不可以在篡改数据之后,同时更改数字签名,使得数字签名解密过的 checksum2 和篡改过的 checksum1 一致呢?这种情况理论上也是不可行的!
当黑客篡改了数据之后,要想重新生成数字签名,就需要使用公证机构的私钥来加密,首先这个私钥就不是一般黑客有能力拿得到的。
黑客如果自己生成一个私钥呢?那么这个时候,客户端拿着公证机构的公钥,也解决不了,此时,客户端解密出错,也可能认为是证书的问题,也会弹出大大的窗口。
OKK,有关 HTTP 的相关知识点就说这么多了,这一期的知识点多且杂,大家还需要好好理解,就这样吧,咱们下期再见,与诸君共勉!!!