目录
1.HTTP是什么?
2.HTTP工作过程
3.HTTP协议格式
3.1.抓包工具使用
eg:抓取"必应"的包
PS:HTTP不同版本号之间的区别
3.2.抓包工具原理
3.3.抓包结果分析
①HTTP 请求:
②HTTP 响应:
3.4.协议格式小结
PS:为什么 HTTP 报文中要存在 "空行"?
4.HTTP请求
4.1.请求地址
PS:查看IP地址
PS:使用 ping 命令查看域名对应的 IP 地址
PS:做完项目部署选择
PS:URL 中可省略部分
PS:关于 URL encode(URL 编码)
4.2.请求方法
4.2.1.GET
--->PS:使用 Fiddler 观察 GET 请求
--->GET请求的特点:
--->PS:关于 GET 请求的 URL 长度问题
4.2.2.POST
--->PS:通过 HTML 中的 form 标签构造 GET 请求
--->PS:通过 HTML 中的 form 标签构造 POST 请求
--->PS:使用 Fiddler 观察 POST 方法
--->POST 请求的特点:
--->PS:(经典面试题)谈谈 GET 和 POST 的区别
4.2.3.其他方法
4.3.请求报头
4.3.1.Host
4.3.2.Content-Length
4.3.3.Content-Type(重要)
--->PS:JSON
4.3.4.User-Agent (简称 UA)
4.3.5.Referer
4.3.6.Cookie
--->可以通过抓包观察⻚⾯登陆的过程(以码云为例):
--->理解登录过程
--->PS:服务器端 VS 客户端
4.4.请求正文
4.4.1.application/x-www-form-urlencoded
4.4.2.multipart/form-data
4.4.3.application/json
5.HTTP响应
5.1.状态码
①200 OK——成功
②404 Not Found——访问页面不存在
③403 Forbidden——没有权限访问
④500 Internal Server Error——服务器错误
⑤504 Gateway Timeout——访问超时
⑥302 Move temporarily——临时重定向
⑦301 Moved Permanently——永久重定向
小结:
5.2.响应报头
5.2.1.Content-Type
1.HTTP是什么?
HTTP (全称为 "超⽂本传输协议") 是⼀种应用非常广泛的应用层协议。本身不传输数据包,只是规定了客户端和服务器端之间的通信格式。
一个完整的应用是由前端+后端构成的,而前、后端之间的通讯是要依靠HTTP来完成的。
这就像消费者在网上买东西一样,商家和买家之间,需要一个快递公司,而HTTP协议就是这个快递公司,其中的请求方法GET/POST相当于不同的快递类型(标准快递/加急快递)。
HTTP 诞⽣于1991年,⽬前已经发展为最主流使⽤的⼀种应⽤层协议,我们平时打开⼀个⽹站,就是通过 HTTP 协议来传输数据的。
2.HTTP工作过程
当我们在浏览器中输⼊⼀个"⽹址"(URL)时,浏览器就给对应的服务器发送⼀个 HTTP 请求,对方服务器收到这个请求之后,经过计算处理,就会返回⼀个 HTTP 响应。这个响应结果被浏览器解析之后,就展示成我们看到的⻚⾯内容。(这个过程中浏览器可能会给服务器发送多个 HTTP 请求,服务器会对应返回多个响应,这些响应⾥就包含了⻚⾯ HTML,CSS,JavaScript,图⽚,字体等信息)。
所谓 "超⽂本" 的含义,就是传输的内容不仅仅是⽂本(⽐如 html,css 这个就是⽂本),还可以是⼀些其他的资源,⽐如图⽚,视频,音频等⼆进制的数据。
通过 F12 打开 chrome 的开发者⼯具,切换到 Network 标签⻚,然后刷新⻚⾯即可看到如下图效果。每⼀条记录都是⼀次 HTTP 请求/响应。
注意:当前搜狗主⻚是通过 https 来进⾏通信的。https 是在 http 基础之上做了⼀个加密解密的⼯作。
3.HTTP协议格式
HTTP 是⼀个⽂本格式的协议,可以通过 Chrome 开发者⼯具或者 Fiddler 抓包(功能更强),分析 HTTP 请求/响应的细节,排查解决项目中的问题。
3.1.抓包工具使用
以 Fiddler 为例。
Fiddler下载地址https://www.telerik.com/fiddler/
安装过程⽐较简单,⼀路 next 即可。所有软件安装路径不要含有中文!!!
当打开Fiddler之后,它就会直接抓取电脑上的一些包,只要有网络请求,Fiddler都会进行拦截和抓取。
可以使⽤ ctrl + a 全选左侧的抓包结果,delete 键清除所有被选中的结果。
eg:抓取"必应"的包
①打开Fiddler工具,删除所有无效的包。
②打开"必应",搜素任意内容,如"111',回车。
③在Fiddler中观察抓包结果。并且可以点击左下角Capturing按钮,让其停止抓包,方便做信息筛选。
- 左侧窗⼝显示了所有的 HTTP请求/响应,可以选中某个请求查看详情。
- 右侧上⽅显示了 HTTP 请求的报⽂内容。(切换到 Raw 标签⻚可以看到详细的数据格式)。
- 右侧下⽅显示了 HTTP 响应的报⽂内容。(切换到 Raw 标签⻚可以看到详细的数据格式)。
- 请求和响应的详细数据,可以通过右下⻆的 View in Notepad 通过记事本打开。
左侧:
- #:相当于id,无实际意义。
- Result:状态码,先看前后端交互是否正常。
- Protocol:协议。
- Host:请求的站点,域名信息。一个Host下有多个URL。
- URL:页面的具体地址。Host和URL合起来可定位到唯一的一个页面。
- Body:返回数据的大小。
- Caching:缓存。
- Content-Type:表示当前抓包的类型。通常在前后端交互时使用json(用于JS数据传输的一种数据格式)、二进制的一些数据formdata文件/流媒体/png等。
- Process:进程,所抓的包是来自于哪个应用的。
- Comments:备注信息。(通常没有)
- Custom:自定义的一些内容。(通常没有)
PS:HTTP不同版本号之间的区别
从http诞生以来,经历了多个版本之间的更新,目前总共有5个版本,最新版本已经到了http 3.0。
①HTTP/0.9
HTTP 0.9是最初的HTTP协议,已经过时。
特点:
- 只支持GET请求。
- 没有协议头。
- 无状态性。
- 只能传输超文本。
这里的无状态性指在客户端发送请求,服务器接收请求并返回结果给客户端后,客户端和服务器的连接会马上断开。这一特性在后面版本的HTTP中也一样。
②HTTP/1.0
这一版本在请求和响应中加入了HTTP版本号,这一特点在之后的版本中保持不变。
相对于HTTP 0.9 新增以下特性:
- 除了GET命令,新增了POST和HEAD命令。
- 不再只接收HTML格式数据,可以设置contentType传输多种数据格式。
- 新增状态码(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)等。
③HTTP/1.1
这是目前最流行的HTTP协议,在有时候做一些小网站的时候会使用。
相对于HTTP 1.0 新增以下特性:
- 引入了持久连接(persistent connection),即TCP连接默认不关闭,可以被多个请求复用。
- 请求和响应都支持Host头域,认为每一个服务器都绑定唯一的一个IP地址。
- 字节范围请求:若客户端此时已经有一部分数据,为节省带宽,可以只向服务器端请求一部分数据,这个功能在请求头的range头域实现。
- 新增了一批Request method:HTTP1.1增加了OPTIONS,PUT, DELETE, TRACE, CONNECT方法。
④HTTP/2.0
为了解决1.1版本利用率不高的问题,提出了HTTP/2.0版本。但目前似乎还没流行起来。
主要新增特性:
- 增加双工模式,也就是不经客户端可以同时发送多个请求,服务器端也能处理多个请求,以此来提高利用率,也是这个版本最大亮点。
- 服务器推送:不经请求向客户端发送数据。
- 二进制分帧层。
- 数据流:将每个请求或相应的所有数据包称为一个数据流,每个数据流有一个ID,规定客户端发出的ID为奇数,服务器端发出的ID为偶数;客户端还可以设置优先级,优先级越高,服务器越优先处理。
- 头信息压缩机制:由于HTTP很多请求头信息中的字段都一样,可以先压缩后发送,而且客户端和服务器端可以同时维护一张头信息表,只用穿输索引号,大大提高效率。
⑤HTTP/3.0
HTTP3.0 在2018年发布,基于谷歌的QUIC,底层使用udp代码tcp协议。
主要提升:
- 使用stream进一步扩展HTTP2.0 的多路复用,传输多少文件就可以产生多少stream,若发生丢包,只需要传输丢失的stream。
- 基于UDP,提高了传输效率,降低延迟。
- 通过引入 Connection ID,使得 HTTP/3 支持连接迁移以及 NAT 的重绑定。
- HTTP/3 含有一个包括验证、加密、数据及负载的 built-in 的 TLS 安全机制。
3.2.抓包工具原理
Fiddler 相当于⼀个 "代理"。
浏览器访问 sogou.com 时,就会把 HTTP 请求先发给 Fiddler,Fiddler 再把请求转发给 sogou 的服务器。当 sogou 服务器返回数据时,Fiddler 拿到返回数据,再把数据交给浏览器。
因此 Fiddler 对于浏览器和 sogou 服务器之间交互的数据细节,都是⾮常清楚的。
代理就可以简单理解为⼀个跑腿⼩弟,你想买罐冰阔落,⼜不想⾃⼰下楼去超市,那么就可以把钱给你的跑腿⼩弟,跑腿⼩弟来到超市把钱给超市⽼板,再把冰阔落拿回来交到你⼿上。这个过程中,这个跑腿⼩弟对于"你"和"超市⽼板"之间的交易细节,是⾮常清楚的。
3.3.抓包结果分析
以下是⼀个 HTTP请求/响应的抓包结果。
所有的请求和响应都是固定的格式。
①HTTP 请求:
- ⾸⾏:[⽅法] + [url] + [版本]
- Header:请求的属性,冒号分割的键值对;每组属性之间使⽤\n分隔。
- 遇到空⾏表示Header部分结束。
- Body:空⾏后⾯的内容都是Body,Body允许为空字符串。如果Body存在,则在Header中会有⼀个 Content-Length属性来标识Body的⻓度。
②HTTP 响应:
- ⾸⾏:[版本号] + [状态码] + [状态码解释](可省略)
- Header:请求的属性,冒号分割的键值对;每组属性之间使⽤\n分隔。
- 遇到空⾏表示Header部分结束。
- Body:空⾏后⾯的内容都是Body,Body允许为空字符串。如果Body存在,则在Header中会有⼀个 Content-Length属性来标识Body的⻓度;如果服务器返回了⼀个html⻚⾯,那么html⻚⾯内容就 是在body中。
3.4.协议格式小结
PS:为什么 HTTP 报文中要存在 "空行"?
因为 HTTP 协议并没有规定报头部分的键值对有多少个,空⾏就相当于是 "报头的结束标记",或者是 "报头和正⽂之间的分隔符"。HTTP 在传输层依赖 TCP 协议,TCP 是⾯向字节流的,如果没有这个空⾏,就会出现 "粘包问题"。
4.HTTP请求
HTTP 交互主要分为两部分:
- HTTP 请求
- HTTP 响应
这⼀去⼀来就完成了⼀次交互了,⽐如浏览淘宝的商品,点击某⼀个商品详情,请求⾥⾯有地址和参数,服务器查询数据之后把结果响应回来,然后浏览器再解析和渲染之后,⽤户就成功的看到商品详情了,这就完成了⼀次请求了。
4.1.请求地址
平时我们俗称的 "⽹址" 其实就是说的 URL (Uniform Resource Locator 统⼀资源定位符)。互联⽹上的每个⽂件都有⼀个唯⼀的URL,它包含的信息指出⽂件的位置以及浏览器应该怎么处理它。URL 的详细规则由因特⽹标准RFC1738 进⾏了约定。
RFC1738https://datatracker.ietf.org/doc/html/rfc1738
⼀个具体的 URL:
https://v.bitedu.vip/personInf/student?userId=10000&classId=100
可以看到,在这个 URL 中有些信息被省略了。
- https:协议⽅案名。常⻅的有 http 和 https,也有其他的类型。(例如访问 mysql 时⽤的 jdbc:mysql )
- user:pass:登陆信息。之前会用,现在不用,存的是用户名和密码,不安全。现在的⽹站进⾏身份认证⼀般不再通过 URL 进⾏了,⼀般都会省略。
- v.bitedu.vip:服务器地址。此处是⼀个 "域名",域名会通过 DNS 系统解析成⼀个具体的 IP 地址。(通过 ping 命令可以看到,v.bitedu.vip 的真实 IP 地址为 118.24.113.28 )(有域名是因为IP地址不好记,IPV4/IPV6,都是32位的。通过域名找到IP地址 -> Map<String, String> -> String类型的key值就是域名,String类型的value值就是IP地址。IP地址是在网络上定位到某台电脑。)
- 端⼝号:定位到某台电脑的某个程序。上⾯的 URL 中端⼝号被省略了。当端⼝号省略的时候,浏览器会根据协议类型⾃动决定使⽤哪个端⼝。例如 http 协议默认使⽤ 80 端⼝,https 协议默认使⽤ 443 端⼝。
- /personInf/student:带层次的⽂件路径,找到去访问程序里面的哪个页面/接口。
- userId=10000&classId=100:参数。查询字符串(query string)。本质是⼀个键值对结构,键值对之间使⽤ "&" 分隔;键和值之间使⽤ "=" 分隔。其中的 key 和 value 的取值和个数,完全都是程序猿⾃⼰约定的。我们可以通过这样的⽅式来⾃定制传输我们需要的信息给服务器。(传参方式:①GET方式,在url中传参。②POST方式,在body中传参。传参格式:?key1=value1&key2=value2&......,"?"表示传参的开始符,在body中传参不需要加"?")
- ⽚段标识:"#"后是某个控件的id。此 URL 中省略了⽚段标识。⽚段标识主要⽤于⻚⾯内跳转。(例如 Vue 官⽅⽂档:(https://cn.vuejs.org/v2/guide/#起步)https://cn.vuejs.org/v2/guide/#%E8%B5%B7%E6%AD%A5,通过不同的⽚段标识跳转到⽂档的不同章节)
PS:查看IP地址
PS:使用 ping 命令查看域名对应的 IP 地址
在开始菜单中输⼊ cmd,打开命令提示符。
在 cmd 中输⼊ ping v.bitedu.vip,即可看到域名解析的结果。
有的电脑上 ping 命令会报错 ping 不是内部或外部命令,也不是可运⾏的程序或批处理⽂件。这种情况是因为有的 Windows10 默认没有启⽤ ping 命令。百度搜索 windows10 启⽤ ping 即可。
PS:做完项目部署选择
- 部署到Linux服务器后,在简历上粘贴项目的IP地址。
- 部署到Linux服务器后,买一个域名,把域名解析到IP上,在项目地址那里写上域名。(简历加分!)
买云服务器用处:
- 用来练习Linux指令。本地是Windows系统,装一个Linux虚拟机问题很多,那么买一个服务器在上面操作反而简单很多。
- 用来写项目地址。简历上项目描述包含:项目名称+项目使用技术+项目功能+项目源码地址+项目演示地址(更直观、快速地了解项目)。
- 一人一个服务器:一个目录下放一个项目。
- 多人一个服务器:用户名和密码共享,创建多个目录,每个目录下放每个人的项目。
PS:URL 中可省略部分
- 协议名:可以省略,省略后默认为 http://。
- ip 地址 / 域名:在 HTML 中可以省略。(⽐如 img, link, script, a 标签的 src 或者 href 属性)。省略后表示服务器的 ip / 域名与当前 HTML 所属的 ip / 域名⼀致。
- 端⼝号:可以省略。省略后如果是 http 协议,端⼝号⾃动设为 80;如果是 https 协议,端⼝号⾃动设为 443。
- 带层次的⽂件路径:可以省略。省略后相当于 / 。有些服务器会在发现 / 路径的时候⾃动访问 /index.html。
- 查询字符串:可以省略。
- ⽚段标识:可以省略。
PS:关于 URL encode(URL 编码)
- 搜索的关键字会在url中的"wd="之后"&"之前存储。
- 像 "/"、"?"、":" 等这样的字符,已经被url当做特殊意义理解了。因此这些字符不能随意出现。 ⽐如,某个参数中需要带有这些特殊字符,就必须先对特殊字符进⾏转义。
- ⼀个中⽂字符由 UTF-8 或者 GBK 这样的编码⽅式构成,虽然在 URL 中没有特殊含义,但是仍然需要进⾏转义。否则浏览器可能把 UTF-8/GBK 编码中的某个字节当做 URL 中的特殊符号。
- 转义的规则如下:将需要转码的字符转为16进制,然后从右到左,取4位(不⾜4位直接处理),每2位做⼀位,前⾯加上"%",编码成"%XY"格式。例如:
"+" 被转义成了 "%2B"。
urlencode工具https://tool.chinaz.com/Tools/urlencode.aspx
urldecode(解码)就是urlencode(编码)的逆过程。
以上过程除了可以用在线编码工具外,还可以通过JS(本身提供了url编码)做url编码处理。
4.2.请求方法
这⾥的⽅法指的是请求的⽅法类型,它的分类有以下⼏个:
方法 | 说明 | 支持的HTTP协议版本 |
GET(最常用) | 获取资源 | 1.0、1.1(主流) |
POST(最常用) | 传输实体主体 | 1.0、1.1 |
PUT | 传输文件 | 1.0、1.1 |
HEAD | 获得报文首部 | 1.0、1.1 |
DELETE | 删除文件 | 1.0、1.1 |
OPTIONS | 询问支持的方法 | 1.1 |
TRACE | 追踪路径 | 1.1 |
CONNECT | 要求用隧道协议连接代理 | 1.1 |
LINK | 建立和资源之间的联系 | 1.0 |
UNLINK | 断开连接关系 | 1.0 |
4.2.1.GET
GET 是最常⽤的 HTTP ⽅法,常⽤于获取服务器上的某个资源(例如查询用户列表)。
在浏览器中直接输⼊ URL,此时浏览器就会发送出⼀个 GET 请求。
HTML 中的 link, img, script 等标签,也会触发 GET 请求。使⽤ JavaScript 中的 ajax 也能构造 GET 请求。
--->PS:使用 Fiddler 观察 GET 请求
打开 Fiddler,访问搜狗主⻚,观察抓包结果:
在上⾯的结果中可以看到:
最上⾯的是通过浏览器地址栏发送的 GET 请求:
下⾯的和 sogou 域名相关的请求,有些是通过 html 中的 link/script/img 标签产⽣的,例如:
有些是通过 ajax 的⽅式产⽣的,例如:
关于 ajax:Asynchronous JavaScript and XML(异步的 JavaScript 和 XML),它的最⼤的优点是在不重新加载整个⻚⾯的情况下,可以与服务器交换数据并更新部分⽹⻚内容。
选中第⼀条观察请求的详细结果:
--->GET请求的特点:
- ⾸⾏的第⼀部分为 GET。
- URL 的 query string 可以为空,也可以不为空。
- header 部分有若⼲个键值对结构。
- body 部分为空。
--->PS:关于 GET 请求的 URL 长度问题
- ⽹上有些资料上描述:get请求⻓度最多1024kb。这样的说法是错误的。
- HTTP 协议由 RFC 2616 标准定义,标准原⽂中明确说明: "Hypertext Transfer Protocol -- HTTP/1.1, " does not specify any requirement for URL length.没有对 URL 的⻓度有任何的限制。
- 实际 URL 的⻓度取决于浏览器的实现和 HTTP 服务器端的实现。在浏览器端,不同的浏览器最⼤⻓度是不同的,但是现代浏览器⽀持的⻓度⼀般都很⻓;在服务器端,⼀般这个⻓度是可以配置的。
4.2.2.POST
POST ⽅法也是⼀种常⻅的⽅法。多⽤于提交⽤户输⼊的数据给服务器(例如登陆⻚⾯)。
通过 HTML 中的 form 标签可以构造 POST 请求,或者使⽤ JavaScript 的 ajax 也可以构造 POST 请求。
--->PS:通过 HTML 中的 form 标签构造 GET 请求
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>通过 HTML 中的 form 标签构造 POST 请求</title> <script src="js/jquery-1.9.1.min.js"></script> </head> <body> <form action="login" method="get"> 用户名:<input name="username" type="text"> </br> <input type="submit" value=" 提交 "> </form> </body> </html>
--->PS:通过 HTML 中的 form 标签构造 POST 请求
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>通过 HTML 中的 form 标签构造 POST 请求</title> <script src="js/jquery-1.9.1.min.js"></script> </head> <body> <form action="login" method="post"> 用户名:<input name="username" type="text"> </br> <input type="submit" value=" 提交 "> </form> </body> </html>
--->PS:使用 Fiddler 观察 POST 方法
在教务系统的登陆⻚⾯,输⼊⽤户名,密码,验证码之后,点击登陆,就可以看到 POST 请求。
点击这个请求,查看请求详情:
--->POST 请求的特点:
- ⾸⾏的第⼀部分为 POST。
- URL 的 query string ⼀般为空。(也可以不为空)
- header 部分有若⼲个键值对结构。
- body 部分⼀般不为空。body 内的数据格式通过 header 中的 Content-Type 指定。body 的⻓度由 header 中的 Content-Length 指定。(通过对比Content-Length的实际值和预期值,来检验数据是否丢失)
--->PS:(经典面试题)谈谈 GET 和 POST 的区别
- 关于语义:GET ⼀般⽤于获取数据(查);POST ⼀般⽤于提交数据(增、删、改)。 (GET 完全可以⽤于提交数据;POST 也完全可以⽤于获取数据)
- 关于传参:GET 的 body ⼀般为空,需要传递的数据通过 query string 传递;POST 的 query string ⼀般为空,需要传递的数据通过 body 传递。
- 关于幂等性:GET 请求⼀般是幂等的;POST 请求⼀般是不幂等的。(如果多次请求得到的结果⼀样,就视为请求是幂等的)标准建议 GET 实现为幂等的,实际开发中 GET 也不必完全遵守这个规则。(主流⽹站都有 "猜你喜欢" 功能,会根据⽤户的历史⾏为实时更新现有的结果)
- 关于缓存:GET 可以被缓存;POST 不能被缓存。(这⼀点也是承接幂等性)
- 关于传输数据量/最大长度限制:标准中没有规定 GET 和 POST 的最大长度限制。但实际中浏览器通常对GET有最大长度限制(不同浏览器限制不同);对POST没有最大长度限制。有的资料上说 "GET 传输的数据量⼩,POST 传输数据量⼤"。这个也是不科学的,标准没有规定 GET 的 URL 的⻓度,也没有规定 POST 的 body 的⻓度。传输数据量多少,完全取决于不同浏览器和不同服务器之间的实现区别。
- 关于安全性:GET 通过 url 传参,在 url 中一眼能看到参数;POST 通过 body 传参,在 url 中看不到参数。有些资料上说 "POST ⽐ GET 请安全"(但也是伪安全,因为可以通过抓包在 body 中看到参数)。这样的说法是不科学的。是否安全取决于前端在传输密码等敏感信息时是否进⾏加密,和 GET、POST ⽆关。
- 关于传输数据类型:有的资料上说 "GET 只能传输⽂本数据,POST 可以传输⼆进制数据"。这个也是 不科学的。GET 的 query string 虽然⽆法直接传输⼆进制数据,但是可以针对⼆进制数据进⾏ urlencode。
4.2.3.其他方法
- PUT 与 POST 相似,只是具有幂等特性,⼀般⽤于更新。
- DELETE 删除服务器指定资源。
- OPTIONS 返回服务器所⽀持的请求⽅法。
- HEAD 类似于GET,只不过响应体不返回,只返回响应头。
- TRACE 回显服务器端收到的请求,测试的时候会⽤到这个。
- CONNECT 预留,暂⽆使⽤。
这些⽅法的 HTTP 请求可以使⽤ ajax 来构造。(也可以通过⼀些第三⽅⼯具)
任何⼀个能进⾏⽹络编程的语⾔都可以构造 HTTP 请求。本质上就是通过 TCP socket 写⼊⼀个符合 HTTP 协议规则的字符串。
4.3.请求报头
请求报头在发送请求时⽤来描述更多消息的,header 的整体的格式也是 "键值对" 结构,每个键值对占⼀⾏。键和值之间使⽤分号分割。
报头的种类有很多,此处仅介绍⼏个常⻅的。
4.3.1.Host
表示服务器主机的地址和端⼝(定位到网络中某一台电脑的某一个程序)。
4.3.2.Content-Length
表示 body 中的数据⻓度,不是字符串的长度,是字节的长度。验证数据传输过程是否丢失。
4.3.3.Content-Type(重要)
表示请求的 body 中的数据格式。
常⻅选项:
- application/x-www-form-urlencoded: form 表单提交的数据格式。此时 body 的格式形如:
title=test&content=hello
- multipart(数据流)/form-data: form 表单提交的数据格式。(在 form 标签中加上 enctyped="multipart/ form-data")通常⽤于提交图⽚/⽂件(存放字节流,16进制的字节构成)。body 格式形如:
Content-Type:multipart/form-data; boundary=----
WebKitFormBoundaryrGKCBY7qhFd3TrwA
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text"
title
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png
PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
- application/json: 数据为 json 格式。body 格式形如:
{"username":"123456789","password":"xxxx","code":"jw7l","uuid":"d110a05ccde64b16a861fa2bddfdcd15"}
关于Content-Type的详细情况https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types
--->PS:JSON
(在查看官方文档时可以查看"菜鸟教程"或"w3cschool",比较通俗易懂)
什么是 JSON ?
- JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
- JSON 是轻量级的文本数据交换格式。是存储和交换文本信息的语法,类似 XML,比 XML 更小、更快,更易解析。
- JSON 独立于语言:JSON 使用 Javascript语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言C、Python、C++、Java、Go等。 目前非常多的动态(PHP,JSP,.NET)编程语言都支持JSON。
- JSON 具有自我描述性,更易理解和编写。
JSON 格式
以 "{" 开始,以 "}" 结束。前后端交互,即使没有数据,也要使用 "{}",表示是以 JSON 格式去传,只是没有内容。
- 表示传一个对象:
{"key1":"value1", "key2":"value2", ......}
- 表示传一组对象:
{ "sites": [ { "name":"菜鸟教程" , "url":"www.runoob.com" }, { "name":"google" , "url":"www.google.com" }, { "name":"微博" , "url":"www.weibo.com" } ] }
这个 sites 对象是包含 3 个站点记录(对象)的数组。
验证 JSON 格式是否正确
4.3.4.User-Agent (简称 UA)
表示浏览器/操作系统的属性。形如:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36
其中 Windows NT 10.0; Win64; x64 表示操作系统信息。
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36 表示浏览器信息。
4.3.5.Referer
表示这个⻚⾯是从哪个⻚⾯跳转过来的。形如:
https://v.bitedu.vip/login
如果直接在浏览器中输⼊URL,或者直接通过收藏夹访问⻚⾯时是没有 Referer 的。
4.3.6.Cookie
HTTP这种传输协议是无状态的,不会记录是谁访问的。为了记录用户信息,不用每次登录都输入用户名和密码,可使用Cookie来解决用户标识问题。
Cookie 中存储了⼀个字符串,这个数据可能是客户端(⽹⻚)⾃⾏通过 JS 写⼊的,也可能来⾃于服务器(服务器在 HTTP 响应的 header 中通过 Set-Cookie 字段给浏览器返回数据)。往往可以通过这个字段实现 "身份标识" 的功能。
每个不同的域名下都可以有不同的 Cookie,不同⽹站之间的 Cookie 并不冲突。
--->可以通过抓包观察⻚⾯登陆的过程(以码云为例):
1) 清除之前的 cookie
为了⽅便观察,先清除掉之前登陆的 cookie。在码云⻚⾯上,点击 url 左侧的图标,选择 Cookie。
然后移除已经存在的 Cookie:
2) 登陆操作
登陆请求:
登陆响应:
可以看到,响应中包含了 3 个 Set-Cookie 属性。
其中我们重点关注第三个。⾥⾯包含了⼀个 gitee-session-n 这样的属性,属性值是⼀串很⻓的加密之后的信息。这个信息就是⽤户当前登陆的身份标识。也称为 "令牌(token)"。
3) 访问其他页面
登陆成功之后,此时可以看到后续访问码云的其他⻚⾯(⽐如个⼈主⻚),请求中就都会带着刚才获取到的 Cookie 信息。
请求你中的 Cookie 字段也包含了⼀个 gitee-session-n 属性,⾥⾯的值和刚才服务器返回的值 相同。后续只要访问 gitee 这个⽹站,就会⼀直带着这个令牌,直到令牌过期/下次重新登陆。
--->理解登录过程
这个过程和去医院看病很相似:
- 到了医院先挂号,挂号时候需要提供身份证,同时得到了⼀张 "就诊卡",这个就诊卡就相当于患者的 "令牌"。
- 后续去各个科室进⾏检查,诊断,开药等操作,都不必再出示身份证了。只要凭就诊卡即可识别出当前患者的身份。
- 看完病了之后,不想要就诊卡了,就可以注销这个卡。此时患者的身份和就诊卡的关联就销毁了。(类似于⽹站的注销操作)
- 又来看病,可以办⼀张新的就诊卡,此时就得到了⼀个新的 "令牌"。
在登录状态可以去操作页面,是因为当前浏览器里存储了登录用户的Cookie信息。
Admin-Token是当前登录用户的密钥,根据这个密钥就能知道当前登录用户是谁。
后端实现登录是通过:
- 用户发一个用户名和密码给后端,后端去查询数据库,判断用户名和密码是否正确。
- 如果用户名和密码正确,允许登录,给用户颁发一个密钥token。这是为了防止他人伪造。
- 如果每次不颁发token,把用户的id存到后端,把用户的id再给前端发过去,前端拿的就是一个固定的id了,如果知道了id后,就可以伪造这个用户进行登录操作了,是极不安全的。
- 怎么解决信任、伪造的问题呢?就需要一个颁发密钥的机制:每一次登录成功后,都会生成一长串、唯一的、不能伪造的token给用户,token里记录的就是用户的id,和用户的身份做关联,每次登录成功,将密钥和登录成功的消息返回给前端,前端将这个token存储起来,以后每次请求时,浏览器会实现一个机制,每一次访问接口时都会将这个token带上,将当前网站下的所有cookie全部都加上,然后传递给后端。
- 后端拿到这个token后,判断这个token是否是有效的token,如果不是当前系统颁发的,那么在内存中/数据库中没有这样的token,就知道是伪造的token了。如果是真实的,就能查到这个token所关联的用户id,就知道用户的权限了,从而进行相应的操作。解决了用户标识的问题,解决了HTTP协议无状态的问题。不用程序员自己业务实现,浏览器自己去实现。
- 如果用户名和密码不正确,直接返回用户名或密码错误给前端,前端直接将结果展示给用户,这一次的业务请求就结束了。
- 如果我的token值被别人劫持了,别人就能用我的信息了。但是由于token是每次都会生成的,当我重新登录时,token就变了,之前劫持的token就用不了了。也算是一种安全的解决方案。
token是可以很方便地去伪造的:
当删除所有cookie信息之后:
刷新当前页面,会返回到登录状态,因为存在cookie里的身份标识丢了:
--->PS:服务器端 VS 客户端
1、定义不同:
客户端:为客户提供本地服务的程序。
服务器端:网络中能对其它机器提供某些服务的计算机系统。
2、程序编写:
客户端:程序不需要客户编写,可以使用IE或者FireFox等浏览器。
服务器端:需要编写Server服务端程序。
3、组成不同:
客户端:浏览器既是客户端。
服务器端:中央处理器、内存、芯片组、I和O总线、I和O设备、电源、机箱和相关软件。
4、储存方式不同:
客户端:不需要储存。
服务器端:包括SAS和SATA、PCIe闪存卡、NVMe闪存和双列直插式内存插槽的实现在内有多种方式部署服务器端闪存。
5、服务对象不同:
客户端:为使用的客户服务。
服务器端:为客户端服务。
--->PS:cookie、session、tooken
前言
- HTTP是一种“无状态”协议,它的每个请求都是完全独立的,每个请求中包含了处理这个请求所需的完整的数据,发送请求不会涉及到状态变更。
- 举个例子:你第一次去A店买了苹果,然后你第二次去买苹果时你和老板说我上次来过,能便宜点不,他说他不认识你,并且无论你去他那买多少次苹果他都不认识你。他只知道有人来买过苹果,具体是谁他不知道。
- 所以在浏览器向服务端请求数据的过程中就延伸出一种严重的问题——数据泄露,许多Web应用程序的安全和正常运行都需要系统能够区分用户并识别用户及其权限。所以这就需要一些机制来为一个HTTP请求提供状态。它们使站点能够在会话期间对各用户做出适当的响应,从而保持跟踪用户在应用程序中的活动(请求和响应)。cookie和token都是典型的解决方案。
①cookie
- cookie指的是浏览器里面能永久存储的一种数据,仅仅是浏览器实现的一种数据存储功能。
- 是由客户端向服务器端发送请求,服务器产生cookie,然后返回给客户端,存放于浏览器的缓存之中。
- 浏览器把cookie以kv形式保存到某个目录下的文本文件内,下一次请求同一网站时,会把该cookie发送给服务器。
- 由于cookie是存在于客户端上的,所以浏览器加入了一些限制确保cookie不会被恶意使用,同时不会占据太多磁盘空间。所以每个域的cookie数量是有限的。
②session
- session从字面上讲就是会话,服务器要知道当前发请求的是谁,因此需要给每个客户端分配不同的身份标识,然后客户端每次向服务器发请求的时候,都带上这个身份标识,服务器就知道这个请求来自于谁了。
- 至于客户端怎么保存这个身份标识,可以有很多种方式,对于浏览器客户端,大家都默认采用cookie的方式。
- 服务器使用session把用户的信息临时保存在了服务器上,用户离开网站后session会被销毁。这种用户信息存储方式,相对cookie来说更安全,所以session存储更重要的数据。
- 可是session有一个缺陷:如果web服务器做了负载均衡,那么下一个操作请求到了另一台服务器的时候session会丢失,session的问题在于前端传来的session_id可以伪造,所以必须在服务器里维护一个session_id的白名单,来验证session_id的合法性。
③token
- token的改进之处就在这里,token通过签名机制,只要前端传来的token能通过签名认证就是合法的,不需要服务器维护任何东西,所有的需要东西都放在token里面。
- token是身份令牌,用于识别用户的身份,是服务器端生成的一串字符串,一般保存在请求头当中,作为客户端进行请求的一个标识。
- 在前端请求后台接口时,为了安全性,一般需要在用户登录成功之后,才能发送其他请求。因此,在用户登录成功之后,后台会返回一个token给前端,这个时候就需要把token暂时保存在本地,每次发送请求的时候,需要在header里边带上token,无需再次带上请求名和密码,这个时候本地的token和后台数据库中的token进行一个验证,如果两者一致,则请求成功。
- 简单的token是由uid用户唯一的身份标识、time当前的时间戳、sign签名、token的前几位以及哈希算法压缩成的一定长度的十六进制字符串组成,为防止token泄露。
- token可以减轻服务器的压力,减少频繁地查询数据库,使服务器更加健壮。
鉴权认证方式 特点 优点 缺点 cookie 1.存储在客户端。
2.请求自动携带cookie。
3.存储大小4KB。
1.兼容性好,因为是比较老的技术。
2.很容易实现,因为cookie会自动携带和存储。
1.需要单独解决跨域携带问题,比如多台服务器如何共享cookie。
2.会遭受CSRF攻击。
3.存储在客户端,不够安全。
session 1.存储在服务端。
2.存储大小无限制。
1.查询速度快,因为是个会话,相当于是在内存中操作。
2.结合cookie后很容易实现鉴权。
3.安全,因为存储在服务端。
1.耗费服务器资源,因为每个客户端都会创建session。
2.占据存储空间,session相当于存储了一个完整的用户信息。
token 1.体积很小。
2.自由操作存储在哪里。
1.安全,因为token一般只有用户id,就算被截取了也没什么用。
2.无需消耗服务器内存资源,它相当于只存了用户id,session相当于存储了用户的所有信息。
3.跨域处理较为方便,比如多台服务器之间可以共用一个token。
1.无状态问题。
2.性能问题。
总结:
session是空间换时间,token是时间换空间。
如果有严格的用户管理要求的用cookie+session的方式,如果没有严格要求推荐使用token方式,会减少很多服务端的压力。
4.4.请求正文
正⽂中的内容格式和 header 中的 Content-Type 密切相关。上⾯也罗列了三种常⻅的情况。下⾯可以通过抓包来观察这⼏种情况,实际的抓包结果⽐较⻓,此处没有全部贴出。
4.4.1.application/x-www-form-urlencoded
抓取码云上传头像请求:
4.4.2.multipart/form-data
抓取教务系统的"上传简历" 功能:
4.4.3.application/json
抓取教务系统的登陆⻚⾯ https://v.bitedu.vip/login:
5.HTTP响应
5.1.状态码
状态码表示访问⼀个⻚⾯的结果。(是访问成功,还是失败,还是其他的⼀些情况...)
类别 | 原因短语 | |
1XX | Informational(信息性状态码) | 接收的请求正在处理 |
2XX | Success(成功状态码) | 请求正常处理完毕 |
3XX | Redirection(重定向状态码) | 需要进行附加操作以完成请求 |
4XX | Client Error(客户端错误状态码) | 服务器无法处理请求 |
5XX | Server Error(服务器错误状态码) | 服务器处理请求出错 |
认识的常⻅状态码:
①200 OK——成功
这是⼀个最常⻅的状态码,表示访问成功。
抓包抓到的⼤部分结果都是 200。例如访问搜狗主⻚:
注意:在抓包观察响应数据的时候,可能会看到压缩之后的数据。形如:
②404 Not Found——访问页面不存在
没有找到资源。
浏览器输⼊⼀个 URL,⽬的就是为了访问对⽅服务器上的⼀个资源。如果这个 URL 标识的资源不存在,那么就会出现 404。
例如,在浏览器中输⼊ www.sogou.com/index.html,此时就在尝试访问 sogou 上的 /index. html 这个资源,如果输⼊正确,则可以正确访问到。但是如果输⼊错误,⽐如 www.sogou.com/index2.html,就会看到 404 这样的响应。
③403 Forbidden——没有权限访问
表示访问被拒绝。有的⻚⾯通常需要⽤户具有⼀定的权限才能访问(登陆后才能访问),如果⽤户没有登陆直接访问,就容易⻅到 403。
例如:查看码云的私有仓库,如果不登陆,就会出现 403。参考链接: https://gitee.com/HGtz2222/blog_python
④500 Internal Server Error——服务器错误
服务器出现内部错误。⼀般是服务器的代码执⾏过程中遇到了⼀些特殊情况(服务器异常崩溃),会产⽣这个状态码。咱们平时常⽤的⽹站很少会出现 500 (但是偶尔也能看到)。
⑤504 Gateway Timeout——访问超时
当服务器负载⽐较⼤的时候,服务器处理单条请求的时候消耗的时间就会很⻓,就可能会导致出现超时的情况。
这种情况在双⼗⼀等 "秒杀" 场景中容易出现,流量剧增;网站受攻击时,会使用多线程,发送很多请求,把资源吃完了,系统崩溃。
⑥302 Move temporarily——临时重定向
临时重定向:域名临时重定向,告诉浏览器域名不是固定重定向到当前目标域名,后期可能随时会更改,因此浏览器不会缓存当前域名的解析记录。
对旧网址没有影响,但新网址不会有排名。
理解 "重定向" 就相当于⼿机号码中的 "呼叫转移" 功能。⽐如我本来的⼿机号是 186-1234-5678,后来换了个新号码 135-1234-5678,那么不需要让我的朋友知道新号码,只要我去办理⼀个呼叫转移业务,其他⼈拨打 186-1234-5678,就会⾃动转移到 135-1234-5678 上。
在登陆⻚⾯中经常会⻅到 302。⽤于实现登陆成功后⾃动跳转到主⻚。响应报⽂的 header 部分会包含⼀个 Location 字段,表示要跳转到哪个⻚⾯。
例如:码云的登陆⻚⾯ https://gitee.com/login ,抓包看到的响应结果:可以看到 header 中的 Location: https://gitee.com/HGtz2222 ,接下来浏览器就会⾃动发送 GET 请求,获取 https://gitee.com/HGtz2222。
⑦301 Moved Permanently——永久重定向
永久重定向:域名永久型调整,即域名永远跳转至另外一个新的域名,之前的域名再也不使用,跳转记录可以缓存到客户端浏览器。
新网址完全继承旧网址,旧网址排名完全清零。
301重定向是网页更改地址后对搜索引擎友好的最好方法,只要不是暂时搬移的情况,都建议使用301来做转址。
当浏览器收到这种响应时,后续的请求都会被⾃动改成新的地址。301 也是通过 Location 字段来表示要重定向到的新地址。
301和302只在搜索引擎的抓取权重上有区别:301(搜索在前面)的收入权重会高于302(搜索在后面)。
【百度会有一个大的爬虫系统,回去爬工信部所有备案的域名,爬这些网站是干嘛的,把这些网站收入起来。我自己在新创建一个网站后需要去工信部备案,表示是合法的,所以以后百度在搜与自己网站相关的关键词时,也能搜到自己的网站。】
例如:
我们之前网站的域名是 a.com,现在替换成了 b.com。但是用户并不知道域名改了,所以还是在浏览器里输入 a.com,Web服务器(apache 或者 ngnix)在收到请求后,在响应中包含:
- 状态码 301 及 b.com。用户的浏览器在收到响应后,自动将输入栏网址改变为 b.com。
- 或者状态码 302 及 b.com。用户的浏览器在收到响应后,输入栏仍是显示旧网址,但是显示的是 b.com的内容。
小结:
- 200 成功
- 301 永久重定向
- 302 临时重定向
- 403 没有权限访问
- 404 访问⻚⾯不存在
- 500 服务器错误
- 502 ⽹关错误(网关是做请求分发的,比如做了一个项目,部署了10份,服务能力会提升10倍。中间会通过网关来进行映射,决定前端的请求放在哪台服务器上)(网关不繁忙,但网关全都挂了,就是502)
- 504 访问超时(网关太繁忙会504)
5.2.响应报头
响应报头的基本格式和请求报头的格式基本⼀致。类似于 Content-Type,Content-Length 等属性的含义也和请求中的含义⼀致。
5.2.1.Content-Type
响应中的 Content-Type 常⻅取值有以下⼏种:
- text/html : body 数据格式是 HTML(响应独有)
- text/css : body 数据格式是 CSS(响应独有)
- application/javascript : body 数据格式是 JavaScript(响应独有)
- application/json : body 数据格式是 JSON(和请求重叠)
在教务系统主⻚,通过 ctrl + F5 ⽅式强制刷新,这四种都能看到:
若要给前端响应图片,会把图片存储到文件系统里面,把图片的地址 url 响应给前端,而不会把图片的具体文件流直接给前端。(节省带宽)
- 云服务器里带宽最贵。固定带宽5M,上行和下行还要除以10,一年要1200元左右;10M带宽,一年要3千多。
- 文件系统的带宽足够便宜,它走的是单独的系统,不会占用服务器的带宽;文件系统的安全性好。
关于Content-Type的详细情况https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types