HTTP协议

1. HTTP是什么

HTTP (全称为 "超文本传输协议") 是一种应用非常广泛的应用层协议.

HTTP是文本协议.

IP,TCP,UDP是二进制协议.

HTTPS加密之后是二进制.

使用浏览器,打开网站,这个过程都是HTTP来支持的.

  • "超文本"的含义:

文本=>字符串

超文本=>除了能够传输字符串,还能传输其它的.图片,字体,视频,音频.

  • HTTP响应:

当在浏览器中输入一个搜狗搜索的 "网址" (URL) 时, 浏览器就给搜狗的服务器发送了一个 HTTP 请 求, 搜狗的服务器返回了一个 HTTP 响应.

这个响应结果被浏览器解析之后, 就展示成我们看到的页面内容,往往主体就是一个HTML内容.

  • 一个网站=前端(网页)+后端(HTTP服务器):

网页 HTML,CSS,JS都是在浏览器上执行的.

都是在访问服务器的时候,从服务器下载到浏览器上,然后才能下载执行.

其它的应用程序,一般都是先下载安装,才能使用.网页是随时用随时下载.

  • 使用网页的优势与劣势:

优势:服务器随时更新,用户就能用上新版本.

劣势:性能有限,很难提供一些复杂的,重复的操作.


2. HTTP 协议格式

 HTTP 是一个文本格式的协议,可以使用抓包工具分析 HTTP 请求/响应的细节.

2.1 抓包工具(Fiddler)的使用

本质上是一个代理.

比如说,我想吃辣条,让我弟去跑腿.

这个时候,我和超市老板完成了交易,但是我们没有直接见面,而是通过我弟来进行的交互.而作为代理,我弟很清楚我和老板之间,交易的细节.

此时抓包工具就可以获取到浏览器和服务器之间的交互细节了.

也就可以拿到HTTP请求,和HTTP响应中的具体信息了.

抓包工具,是一种代理.

但是代理又不仅仅只是抓包工具,还有很多种体现形式.

代理客户端的,叫正向代理.

代理服务器的,叫反向代理.

左侧是当前机器上有哪些HTTP数据报在交互.

不仅仅能抓浏览器,而且能抓到所有程序的.电脑上的很多程序,都在后台和服务器悄悄地交互.


选中某个数据之后,右侧就能显示出详细信息.

右上角显示的是请求的详情. 

右下角显示的是相应的内容.


这个就是抓取搜狗主页,交互过程. 


 这些标签页,就是站在不同的视角来解析请求和响应的.

最主要使用的方式是Raw.显示的HTTP原始的数据内容.

当前HTTP响应,经常会进行压缩(节省带宽)(响应可能比较大).点击就会解压缩.

3. HTTP请求

 

3.1 认识URL 

URL:请求,就是客户端(浏览器)给服务器发起的一个数据.

这里要明确描述出,要访问的服务器是什么,要访问的服务器的资源是什么.

3.1.1 基本格式

出自于RFC标准文档.

举个例子: 

虽然认识了query string(查询字符串)的格式,但不知道内容和含义.(这里的键和值的含义,都是程序员自定的).

实际上,URL来说,上述的几个部分,都是可以省略的,不是哪个部分必须得有.

3.1.2 URL中的可省略部分

  • ①IP地址/域名省略,此时相当于是访问当前服务器的地址.

比如说:

访问B站主页,请求里须带有B站域名,响应内容就是B站主页的HTML.

这个HTML里又会触发一些其它的HTTP请求,这些后续触发的HTTP请求,就可以省略IP.

省略IP相当于使用和刚才获取B站HTML一样的IP.

  • ②端口号省略

相当常见.

省略时,浏览器会自动加上端口.(这个端口表示的是访问目标服务器的哪个端口)

如果是HTTP协议,自动添加的端口就是80.

如果是HTTPS协议,自动添加的端口就是443.

  • ③带层次的路径省略

比如:

https://www.sogou.com/

如果省略,相当于访问的就是/,/称为根目录.

服务器提供的资源,也是类似于目录结构一样的树形结构来组织的.

既然是树,就会有树根./就是根节点.

通过根节点就会对应到服务器的主页.(约定俗称的规则)

  • ④查询字符串省略

有和没有,都是可以让后端代码根据情况来处理.

正是上述灵活性,是HTTP可以根据不同的需求场景,进行一些"自定制"工作,也就是HTTO协议成了非常广泛使用的协议.

3.1.3 URL encode

可以看出输入的C++,这里显示为C%2B%2B?

发现,当我们输入www.sogou.com/index.html的时候,页面就变了.

这个页面就会多了一些按钮,点击按钮,就能跳转.(html中的a标签,带有一个url)


  • url里面就是带有query string的.

query string中可能会带有一些特殊符号.而这些特殊符号,可能在url本身就有一定的含义,就导致浏览器/服务器解析失败.

C++中+就属于特殊符号=>%2B.

:/?&=#同理,都需要转换.

url encode本质上就是转义字符!!!(不是\那种,另外一套规则)

  • 转换规则:

把要转换的内容的二进制的每个人字节,都使用十六进制表示出来,然后每个字节前面加上一个%.

经过url encode之后,此时query string中就不会出现特殊含义的符号,浏览器和服务器才能正确识别.

3.2 认识方法(method)

HTTP请求的方法:

其中GET最常用,其次是POST.

方法描述的是"语义",即这次请求要干嘛.

GET:从服务器获取xxx

POST:向服务器传输一个xxx

实际上,GET,POST......不一定遵守之前的语义了.

 

3.2.1 GET方法

GET请求一般没有body.

3.2.2 POST方法

POST请求最常见的场景:登录和上传

①登录

空行,相当于是一个分隔符,分割了header和body.描述了body是从哪开始的.

body里的格式,其实是可以又很多种.

此时这个body格式,和刚才的query string非常类似.也是键值对,只不过是经过了urlencode的.

在登陆场景中,这里就会包含当前这次登录的用户名和密码等认证信息.

密码是加密的,一般密码是不会明文传输的.


②上传

此处的Value就是把整个图片都进行转码,转成字符串在这里填写.

3.2.3 POST和GET的区别

①最主要的区别,就在于:

  • GET是把一些自定义的数据放到query string里,body通常是空的.
  • POST是把一些自定义的数据放到body里,query string通常是空的.

都是要传输给服务器,放哪都是放,本质上没什么区别.

放在URL中,用户能直接看到.

放在body中,用户没法直接看到.


②上传和登录,还是使用POST更多:

  • 登录的时候,涉及到用户名密码,属于比较敏感的信息,直接展示在URL里,会给用户造成一种"不安全"的错觉.
  • 上传的时候,涉及到的内容比较长,比较多,直接放到URL里,显示不美观.

因为POST和GET数据放哪里本质上都可以,两者经常也可以相互替代!


[经典面试题]盖棺定论:GET和POST没有本质区别!!!

从习惯用法上来看,

  • GET通常把数据放到query string中,用户能看到,浏览器收藏夹也能收藏.
  • POST通常把数据放到body里,用户不能看到,收藏夹也不能收藏.

注意:网上有些资料,对于GET和POST的区别,解释并不正确.

  • 1.比较长的数据放到body中(使用POST),原因是GET请求中的URL长度有限制.

×首先,RFC标准文档,明确说明了,对于URL的长度不做限制要求.

其次,当前的资源有限,当时的浏览器对于URL确实有限制,具体限制了多长,看不同的浏览器.(老黄历)

  • 2.POST比GET更安全.

安全指的是,我们传输的数据,不容易被黑客截获,或者被截获了不容易被破解.

POST只是把传输的数据让普通用户没法直接看到,不影响黑客截获.

保证安全的关键,是对传输的敏感数据,进行加密!!!

  • 3.GET和POST语义不同.

设计者最初是赋予了不同语义,但实践中不一定完全遵守.

比如有的公司,设计的所有接口都是POST.有的公司,同时提供GET和POST.

  • 4.GET是幂等的,POST不是幂等的.(REC文档上,建议这么设计)

幂等:给相同的输入,每次都是相同的输出.

设计互联网产品,有些时候,也是要考虑幂等性的.

有的时候,期望是幂等的,有的时候,不幂等.

举个例子:像广告这种,就不能是幂等的,要根据用户,时间,地点,广告投放时间,广告主的出价情况......随时做出改变.

  • 5.GET请求可以被缓存,POST请求不能被缓存.

有些操作,可能比较耗时,与其每次都重新计算,不如把结果保存下来.下次需要用的时候,直接获取.(缓存的前提是,幂等)


除了get和post还有哪些方法?(简单了解)

3.3 认识请求报头(header)

请求报头的整体的格式也是"键值对"结构.

每一行是一个键值对.

键和值直接使用 :空格来分割.

query string/body中的键值对,完全是程序员自定义的.

header中的键值对,主要是标准规定的.(有哪些键,对应的取值有哪些,都有规定),也有可以自定义的部分.

比较重要的:

Host 表示服务器主机的地址和端口
Content-Length 表示body中的数据长度
Content-Type 表示请求的body中的数据格式

3.3.1 Host

Host里的内容,不是在url中​​​​​​​已经有了吗,为什么还要再表示一遍?

通常情况下,Host里的内容和url是一致的,但是也有例外.比如使用了代理,就不一样了.

3.3.2 Content-Length

描述了body的长度是多少字节.

有的请求有body,有的没有.

如果没有这个body,这个字段就可以没有.

如果有body,这个字段必须有.否则就是非法请求.

body是从空行开始的.

从空行这里开始数,数Content-Length这么长,就是body结束了.

这是为了解决粘包问题.

  • HTTP基于TCP.

当浏览器连续给服务器发起多个HTTP请求的时候,或者服务器连续多个返回HTTP响应的时候,服务器或者浏览器如何区分,从哪到哪是一个完整的HTTP数据呢?

1.使用分隔符

2.使用长度.

  • HTTP两个都有:

如果是GET,没有body,使用空行,作为结束标记了.

如果是POST,有body,使用长度,区分结尾了.

3.3.3 Content-Type

针对这个数据,如何解析?如何理解?

HTTP协议有很多用途,传输的数据也有很多种类.

在HTTP请求中,Content-Type有三种主要的情况:

很多网站都会使用json,教务系统就是如此.

  • 如果是响应,情况更复杂:

可能是

html:text/html

css:text/css

js:application/javascript

json:application/json

图片:image/png  image/jpg

纯文本: text/plain

通过Content-Type就可以区分出body的数据的格式是什么.

尤其是浏览器,需要根据不同的格式来决定如何处理.

3.3.4 User-Agent(UA)

主要包含的就是当前机器的系统和浏览器的版本.

在浏览快速发展的时候,新的浏览器支持的功能更多,旧的支持的更少.

同一时刻,市面上有的人使用新的,有的人使用旧的.

  • 举个例子,当你在开发一个网站时,是否要让这个网站带有视频音频js等功能呢?

因此,浏览器在发起HTTP请求的时候,要向服务器自报家门,告诉服务器我现在使用的是什么系统,什么浏览器上网,服务器就可根据这个信息,来分别对待.

实现兼容.让两边都满足需求.

老版本的返回简单网页,新版本的返回复杂网页.

UA现在主要用来区分,PC端(Windowsj/Mac)还是移动端(Android/IOS).

3.3.5 Referer

描述了,当前页面从哪里来.

如果你是通过浏览器地址来直接输入url/点击收藏夹打开的网页,这个请求中是不带Referer的,但如果是点击了某个网页的内容,产生了跳转,就是带Referer.

如上所述.此时Referer就是刚才的搜素结果页.


Referer是明文传输的.

是否会有人把Referer给偷偷改了呢?

在2014年左右的时候,这是一个相当普遍的现象!

是谁在修改???运营商(移动,联通,电信)

1.是否有能力?

有.访问百度/搜狗,流量都是通过运营商的设备(路由器/交换机)进行转发的.完全可以在路由器上搞个程序,分析请求的情况,如果发现是这种广告类的跳转请求,就修改Referer.

2.是否有动机?

有.运营商也有自己的广告平台.

把Rerfer改成了自己广告平台的Referer!

本来这次请求,是搜狗给广告主带来的,结果Referer被改了之后,在广告主看来,请求就是运营商的了,就会提高对运营商的营收.

当然运营商不是把全改,只改一小部分.

这个行为称为"运营商劫持",违法.

使用HTTPS,进行加密传输,这个时候情况就不一样了.

3.3.6 Cookie

是浏览器本地存储数据的一种机制.

键值对之间,使用;分割.键和值之间,使用=分割.

与此同时,用户拿着网页,操作的过程中,也会产生很多"临时性"的数据.

像临时数据,有的可以放到服务器这边存储(下次就能直接获取到了)

有的不太重要的,就直接放到浏览器这边存储(下次访问也可以直接用,但是换个电脑可能就没了)

其中,Cookie就是一个主要的保存机制.

比如,我在B站观看视频的时候,勾选"循环",就可以在Cookie中写入一个数据"循环"=true

浏览器就会自动存储这个数据(硬盘),后续再次访问B站,浏览器就能自动把这个数据读出来,并且放到HTTP请求中.

B站就知道当前用户是否希望开启循环了.

  • 那浏览器要保存数据,为什么要放到Cookie中,直接放到硬盘,写入一个文件不行吗?

当然不行.

如果让网页能够轻易访问你的文件系统,非常危险!!!

如果网站给你电脑上写个病毒,或者直接把你硬盘上已有的数据给删掉......

为了保证安全,浏览器会对网页的功能做出限制(禁止直接访问硬盘,就是其中一个规则)

为了保证安全,同时又能存储数据,浏览器就提供了Cookie功能.

是按照键值对的方式来存储一些字符串,这些键值对往往都是服务器返回回来的,浏览器把这些键值对按照"域名"维度(不同的网站,Cookie是独立的,这些内容,都是程序员自应用的,类似于query string),分类存储.

一个网站,Cookie中会存储很多键值对.

往往会有一个很重要的键值对,是用来表示用户的"身份信息"的.

标识当前请求是来自于哪个用户的.

尤其是有的时候,登录了一个网站之后,后续再次访问这个网站的时候,都不用重新登录!!!

并且关了电脑,第二天再次访问,仍然不必重新登录.(服务器能识别登陆状态)

为了实现身份识别的效果,不仅仅需要Cookie来支持,在服务器这边,也需要一个Session机制来支持.

怎么完成配合呢?

举个例子:

在医院的看病流程是什么样?

如果是第一次来到这个医院,首次挂号的时候,会办一张就诊卡.同时在医院的系统里,会给你创建一个电子档案.

就诊卡里,存储了患者的身份标识.是唯一的.

可以把这些电子档案,想象成使用hash表来组织.key就是身份标识,value就是电子档案的详情.

当排到我之后,第一件事是刷一下就诊卡.此时各种信息,就显示在医生的电脑上了.

刷卡的时候,读卡器就读到了芯片中我的身份标识,就可以通过这个身份标识找到了对应的电子档案,也就知道我的详细情况了.

首次访问网站,注册不考虑,登录成功之后,就相当于,网站给你一个就诊卡(身份标识)

身份标识就通过服务器返回给浏览器的响应,保存在浏览器的Cookie中了(键值对)

与此同时,网站服务器那边,也会创建出一个对应的Session(电子档案),Session中就会记录我的一些关键信息.

网站服务器肯定不止一个用户,有很多用户,每个用户都有自己的

Session,并且他们的SessionId各不相同,服务器就会使用类似于hash表这样的方式,以SessionId为key,以Session为value,把所有的数据组织起来.

后续访问网站的其它页面(相当于去各个科室检查),都会在请求的Cookie字段中,带上刚才这里的SessionId(就是先刷卡),服务器就可以根据SessionId就知道了你当前用户的身份信息了.


  • 简单总结:

4. HTTP响应

4.1 状态码

状态码,就是对这次响应的定性.(成功,失败等情况)

200表示成功(计算机中,通常会使用"数字表示结果,使用不用的数字表示不同的失败原因")

  • 常见的状态码:

成功: 200OK

重定向: temporarily 重定向,浏览器跳转到其它的页面上

请求错误: 403 Forbidden 没有权限      404 Not Found 你要访问的资源不存在

服务器错误: 502 Bad Gateway 服务器挂了   Timeout 服务器响应超时了(多半是服务器出问题了)

  • [面试题]你都知道哪些HTTP状态码,都是什么意思?

重定向:

举个例子:"呼叫转移"

比如说我有一个手机号码:155,某一天我换了个手机号码:166.

就可以去运行商,办理呼叫转移业务.如果有人拨打155,就自动转接到166上.

HTTP的重定向,就是这么搞的!!!

 

5. 构造HTTP请求的四种方法

实际开发中,经常需要能够手动的构造出HTTP协议的请求:

1.通过html的form表单

2.通过js的ajax

3.java代码

4.借助一些第三方工具

5.1 通过 form 表单构造 HTTP 请求

HTML也是一种编程语义,和Java风格差异很大.

描述一个"形态",一个网页上,都有什么.

Java是在描述一个逻辑,先干什么,后干什么,是"动作".

  • html非常有特点:

1.由标签构成,标签可以成对出现,也可以单独出现.

2.标签可以嵌套.


下面通过html中的form标签(表单)构造HTTP请求:


抓包:

form表单,只能支持get和post!!!

5.2 通过 ajax 构造 HTTP 请求

asynchronize 异步

同步的等待,等待的职责是放到了发起者的身上.

异步的等待,等待的职责是放到了被发起者的身上.

ajax是一种异步的通信方式.

通过代码,发起了http请求,请求发出去之后,js代码就继续向下执行了.

当服务器的响应回来了之后,就会自动的通知到代码中,进一步就能处理响应了.

js中,{ }表示的是js的对象.(键值对)

{ }里可以有多个键值对.

键值对之间,用,分割.键和值之间,使用 :分割.

键固定都是string类型,可以写'也可以写"也可以不写.

值可以是数字,字符串,数组,对象.

这里的type,不仅支持get和post,也支持其它各种方式.


抓包:

 

5.3 通过 Java socket 构造 HTTP 请求

java等一系列代码:

使用Java构造,本质上就是一个TCP的客户端.

创建一个Socket对象,往里面按照HTTP协议的格式写数据即可.

5.4 通过postman构造 HTTP 请求 

使用第三方工具,构造HTTP请求.

Postman

并且这里同时可以生成代码:

6. HTTPS

HTTPS也是基于HTTP的,HTTPS就是在HTTP的基础上,进行了加密.

6.1 加密是什么

明文:真正要传输的数据.

密文:经过加密之后的数据.

密钥:在加密和解密过程中起到关键作用.

对称加密:加密和解密,使用的是相同的密钥.

非对称加密:加密和解密,使用的是不同的密钥.

分别称为"公钥"和"私钥",使用公钥加密,私钥就能解密.反之亦然.

6.2 HTTPS的工作过程 

最简单的保证安全的做法: 

引入对称密钥,针对传输的数据(HTTP的header和body)进行加密

 

6.2.1 引入对称加密 

每个客户端,都需要有一把自己的对称密钥(不同客户端的密钥也要不同)

如果客户端生产了密钥,就需要把密钥传输给服务器.


那么问题来了:

此时,黑客已经知道了密钥,后续使用这个密钥加密传输,传输的数据能被黑客解密.

那么就需要想办法,把密钥安全的传输到对端.

需要对这个密钥进行加密.

那如果使用对称密钥对刚才的对称密钥进行加密,还是不行.

此时,如果继续使用对称加密,不管几层,都不安全.

那么就使用非对称加密,针对对称密钥进行加密了.

6.2.2 引入非对称加密 

此处使用非对称加密,只是用来针对对称密钥进行加密,而不是加密http的数据.

后续数据的加密还是使用对称加密的.

非对称加密,运算量很大,效率比较低.

对称加密,运算量小,效率更高.


对上述的过程,还存在一个严重的问题,中间人攻击:

黑客可以使用中间人攻击的方式,仍然能够拿到对称密钥.

解决中间人攻击的关键,需要让客户端能够确认当前收到的公钥,确实是服务器返回的,而不是黑客伪造的!!!

引入了证书机制.

6.2.3 引入证书

需要有一个第三方的认证机构,通过第三方机构作保,来确认当前的公钥是有效的.

服务器会向第三方公证机构申请证书,这个证书里,就会包含很多的属性:

网站的域名,证书过期时间,公钥,数字签名......

这个数字签名,是针对其它数据属性进行的一个验证的机制.

公证机构,在生成证书的时候,会先针对证书中的其他属性,生成校验和.

公证机构,还会使用自己的私钥(不是服务器的私钥)针对上述校验和进行加密,这样其他人就无法重新生成这个校验和.

客户端拿到证书之后,就会对证书进行验证.(检查一下证书是否合法,是否被篡改)

客户端持有认证机构的公钥,就可以针对数字签名进行解密,得到了校验和的明文.

接下来客户端就可以按照同样的算法,把证书中的其它属性再算一次校验和,和证书中的校验和进行对比,判断证书.

  • 问题1:

如果黑客把证书的数据篡改了(比如把公钥替换成了自己的)?

此时校验和不同,客户端会发现.

  • 问题2:

黑客能否对数字签名进行替换?

不能!!!

数字签名,是先计算校验和,在使用认证机构的私钥进行加密,黑客不知道认证机构的私钥是什么,所有无法重新对校验和进行生成数字签名的过程.

  • 问题3:

黑客是否自己也去第三方机构,申请一个证书,把整个证书替换成自己的?

黑客可以这么做,但是没用.

证书中有网站的域名,黑客证书的域名肯定不能和网站的域名一样,审核无法通过.

当然,黑客可以把自己伪装成认证机构,骗客户端按照自己的公钥,此时就可以光明正大的替换证书中的数字签名.


 

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-03-30 16:14:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-30 16:14:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-30 16:14:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-30 16:14:02       20 阅读

热门阅读

  1. taskkill /f /fi “windowtitle eq 窗口标题“ /t 踩坑

    2024-03-30 16:14:02       16 阅读
  2. 云备份客户端业务实现逻辑

    2024-03-30 16:14:02       19 阅读
  3. JVM之堆

    JVM之堆

    2024-03-30 16:14:02      15 阅读
  4. 面向对象设计之单一职责原则

    2024-03-30 16:14:02       24 阅读
  5. kubuntu23.10安装sdl2及附加库和 sfml2.5.1

    2024-03-30 16:14:02       19 阅读
  6. 动态堆栈类及括号匹配(考察类的构建与应用)

    2024-03-30 16:14:02       18 阅读
  7. python知识点记录

    2024-03-30 16:14:02       21 阅读
  8. JVM基础

    JVM基础

    2024-03-30 16:14:02      18 阅读