1.HTTP是什么HTTP全称为"超文本传输协议",是用于从万维网(WWW:World Wide Web)服务器传输超文本到本地浏览器的传送协议,不仅能传输文本,还能传输图片,传输音频文件,视频以及其他各种数据......HTTP 是一个无状态(stateless)协议,也就是说服务器不维护任何有关客户端过去所发请求的消息。这其实是一种懒政,有状态协议会更加复杂,需要维护状态(历史信息),而且如果客户或服务器失效,会产生状态的不一致,解决这种不一致的代价更高。是一种广泛应用的应用层协议,基于TCP/IP通信协议来传递数据的,默认端口为80
其中HTTP1.0,HTTP1.1,HTTP2.0均为TCP实现,HTTP3.0基于UDP实现.
现如今主要使用HTTP1.1,目前Google/Facebook等公司的产品已经支持HTTP3.0了 当我们在浏览器中输入一个百度的"网址"(URL)时,浏览器就会给百度服务器发送一个HTTP请求,百度服务器返回了一个HTTP响应
这个响应结果被浏览器解析之后,就展示成我们看到的页面内容,(这个过程中浏览器可能会给服务器发送多个HTTP请求,服务器会对应返回多个响应,这些响应里就包含了页面HTML,CSS,JavaScript,图片,字体等信息)
HTTPS可以认为是HTTP的升级版,区别在于引入了一个加密层,安全性更高一些
HTTP协议是一种典型的"一问一答模型"的协议
客户端->服务器 客户端发一个请求,服务器返回一个响应(一一对应),如打开网页这种场景
一问多答:下载一个大文件
场景:下载 10GB 游戏安装包、浏览器并行加载多张图片。多问一答:上传一个大的文件
场景:上传 5GB 视频到网盘、提交带多张图片的表单。多问多答:远程桌面(远程控制,画面 / 指令持续交互)2.理解应用层协议和工作过程 理解应用层协议
我们之前学过的TCP/IP,已经知道目前数据能够从客户端进程经过路径选择跨网络传送到服务器端进程(IP+Port)
当我们把数据从A端传送到B端,TCP/IP解决的是顺丰(传送+路径选择)的功能,而两端还要对数据进行加工处理或者使用,所以我们还需要一层协议,叫做应用层协议,其中经典协议之一就是我们所说的HTTP协议负责 “定义数据的用途和格式”
理解HTTP协议的工作过程
当我们在浏览器中输入一个"网址",此时浏览器就会给对应的服务器发送一个HTTP请求,对方服务器收到这个请求之后,经过计算处理,就会返回一个HTTP响应
事实上,当我们访问一个网站的时候,可能涉及不止一次的HTTP请求/响应的交互过程。
可以通过chrome的开发者工具,Fiddler抓包等观察到这个详细的过程
3.Fiddler抓包3.1下载
官方下载地址: https://www.telerik.com/fiddler傻瓜式下载安装,一路next即可3.2抓包 抓包程序也是一种代理,代理分为正向代理和反向代理
正向代理:类似于我想去超市买东西,但由于懒,我让妹妹帮我去超市买,
此时我是客户端,我的妹妹就叫"正向代理"反向代理:妹妹到超市后,问老板买的东西在哪,老板也比较懒,于是告诉儿子东西在哪让自己的儿子去拿给我的妹妹,此时老板是服务器,老板的儿子就叫做"反向代理" 维度正向代理反向代理代理对象代理客户端(替客户端向服务器发送请求)代理服务器(替服务器接收客户端的请求)隐藏的身份隐藏客户端的真实 IP(服务器不知道客户端是谁)隐藏服务器的真实 IP(客户端不知道访问的是哪台服务器)典型场景- 科学上网(突破地域限制)
- 客户端加速(缓存常用资源)
- 企业内网客户端访问外网(统一出口管理)- 负载均衡(将请求分发到多台服务器)
- 网站防护(WAF 作为反向代理过滤恶意请求)
- 静态资源缓存(CDN 节点作为反向代理加速内容分发)示例工具 / 服务VPN(部分场景)、企业级代理服务器Nginx、HAProxy、CDN(如 Cloudflare)、负载均衡器客户端感知客户端需手动配置代理服务器地址(知道代理存在)客户端无需配置(不知道代理存在,以为直接访问服务器)
抓包前的注意事项:
确保你的电脑上退出了其他的代理软件
fiddler也是代理,可能会和其他代理冲突,导致不能正确抓包
vpn/浏览器插件,就可能和fiddler冲突
不用卸载,退出即可2.由于当前网络上大部分网站都是HTTPS,需要开启fiddler的HTTPS功能
(一次性操作)
启动Fiddler即可开始抓包
确保左下角Capturing亮起
左侧是抓到的HTTP数据列表
右侧为请求和响应,Raw为原始的,列出的就是原本HTTP请求的模样解决乱码问题
此处的乱码是二进制,是压缩后的
在二进制的角度上对数据进行重新编码,保证信息量不变,体积缩小,体积小了传输时消耗的带宽就低了,带宽是互联网中最贵的硬件资源,此时用cpu资源来换带宽资源
例:aaabbbbccccc => 3a4b5c
3.3抓包内容详解 请求Request
首行 [方法]+[url]+[版本]
请求头Header
请求的属性,冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束
从第二行开始的若干行一直到空行结束,每一行都是一个键值对,键和值之间使用:空格分割
HTTP中,请求头里的键值对都有哪些,是HTTP标准规定的
不同的请求头,都有特定的含义,但是标准也允许用户自定义一些请求头
空行
请求头的结束标记,因为 HTTP 协议并没有规定报头部分的键值对有多少个,使用空行就相当于是报文的结束标记或报文和正文之间的分隔符正文
HTTP一般来说,GET 往往是不带 body,POST往往是带body
一般登陆页面为POST请求
响应Reponse
首行
响应头
键值对.每一行是一个键值对,不确定几行,以空行结尾,键和值之间使用:空格分割
键值对也是标准规定的
有的键值对,只能出现在请求中,有的只能出现在响应中,有的呢都能出现~~
空行
正文
为什么HTTP报文中要存在"空行"?
因为HTTP协议并没有规定报头部分的键值对有多少个.空行就相当于是"报头的结束标记",或者是
“报头和正文之间的分隔符"
HTTP在传输层依赖TCP协议,TCP是面向字节流的.如果没有这个空行,就会出现"粘包问题"
4.HTTP请求 4.1认识URL
URL的基本格式
平时我们俗称的"网址"其实就是说的URL(UniformResourceLocator统一资源定位符).
互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。
URI 唯一资源标识符,可以简单地理解成URL是URI的一种实现
URI 的核心:“唯一标识”(不管用什么方式);URL 的核心:“唯一标识 + 定位方法”(是 URI 的一种实用形式)。代码语言:javascript复制协议类型:[//[访问资源需要的凭证信息@]服务器地址[:端口号]][/资源层级 UNIX 文件路径]文件名[?查询字符串][#片段标识符]协议方案名:URL给哪个协议使用的
https:协议方案名. 常见的有 http和 https,也有其他的类型.(例如访问mysql 时用的
jdbc:mysql)登录信息(认证):已经过时见不到了....服务器地址:可以是IP也可以是域名
域名会通过DNS系统解析成一个具体的IP地址
服务器端口号:IP是确定唯一的主机,端口号是确定主机上的程序
日常所访问的URL中端口号可能会被省略了.当端口号省略的时候,浏览器会根据协议类型自动决定使用哪个端口.例如http协议默认使用80端口,https协议默认使用443端口.带层次的文件路径:确定服务器上的具体资源(包含很多网页,图片等)查询字符串(query string):键值对结构,针对访问的资源进行补充说明
本质是一个键值对结构,键值对之间用&分隔开,键和值之间用=分隔
query string中的内容是键值对结构.其中的key和value的取值和个数,完全都是程序猿自己约定的,我们可以通过这样的方式来自定制传输我们需要的信息给服务器。 举例:你在百度搜 “苹果”,网址可能是 https://www.baidu.com/s?wd=苹果&rsv_spt=1
这里的 ?wd=苹果&rsv_spt=1 就是查询字符串。
片段标识符:表示一个页面中的某个部分,常用于页面内跳转常见于一些文档类网站
片段标识符就是网址里的 “书签”,让你一步到位找到网页里的某个具体内容,而且这串东西只在浏览器里起作用,服务器根本不管它(服务器只看 #前面的部分)4.2url encode介绍
转义,让"特殊字符"在网址中能正常传输
当我们使用搜狗浏览器搜索C++,用Fiddler进行抓包的时候,会得到以下URL
代码语言:javascript复制GET https://www.sogou.com/web?query=C%2B%2B&_asf=www.sogou.com&_ast=&w=01019900&p=40040100&ie=utf8&from=index-nologin&s_from=index&sourceid=9_01_03&sessiontime=1752049959495 HTTP/1.1query=C%2B%2B,我们发现,++怎么变成了%2B%2B,我们通过url解码工具发现%2B对应的就是+
需要url encode的原因:
这是因为像/、?、:等这样的字符,已经被url当做特殊意义理解了,因此这些字符不能随意出现.如果某个参数中需要带有这
些特殊字符,就必须先对特殊字符进行转义,即urlencode一个中文字符由UTF-8或者GBK这样的编码方式构成,虽然在URL中没有特殊含义,但是仍然需要进行转义,否则浏览器可能把UTF-8/GBK编码中的某个字节当做URL中的特殊符号转义的规则:
将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式。
但是现在网上有很多现成的可以进行转码的工具,因此需要的时百度寻找在线工具即可
5.HTTP的方法 方法就是描述了这个HTTP请求的"动作"
方法说明支持的 HTTP 协议版本GET获取资源1.0、1.1POST传输实体主体(提交数据)1.0、1.1PUT传输文件(一般用于上传)1.0、1.1HEAD获得报文首部(仅响应头)1.0、1.1DELETE删除文件 / 资源1.0、1.1OPTIONS询问服务器支持的方法1.1TRACE追踪请求 - 响应传输路径1.1CONNECT要求用隧道协议连代理1.1LINK建立与资源的关联1.0UNLINK断开资源关联关系1.0
5.1GET方法 最常用的HTTP方法,常用于获取服务器上的某个资源
在浏览器上直接输入一个URL,此时浏览器就会发出一个GET请求
另外,HTML中的 link,img,script等标签,也会触发GET请求.
特点:
首行里面的第一个部分就是 GETURL 里面的 query string 可以为空,也可以不为空GET 请求的 header 有若干个键值对结构GET 请求的 body 一般是空的 关于GET请求的URL长度问题
没有对URL的长度有任何的限制.
实际URL的长度取决于浏览器的实现和HTTP服务器端的实现.在浏览器端,不同的浏览器最大长度是不同的,但是现代浏览器支持的长度一般都很长;在服务器端,一般这个长度是可以配置的.
搜狗页面的请求:
5.2POST方法 POST 方法也是一种常见的方法,多用于提交用户输入的数据给服务器(如登录页面)/上传文件。以下几种方法都会触发 POST 方法的请求
通过 HTML 中的 form 标签可以构造 POST 请求使用 JavaScript 的 ajax 可以构造 POST 请求 特点:
首行第一个部分就是 POSTURL 里面的 query string 一般是空的POST 请求的 header 里面有若干个键值对POST 请求的 body 一般不为空(body 的具体数据格式,由 header 中的 Content-Type 来描述;body 的具体数据长度,由 header 中的 Content-Length 来描述 教务系统登陆界面:
5.3经典面试题之GET和POST的区别 两个方法没有本质的区别,GET能用的场景换成POST也能用,POST能用的场景换成GET也可以
语义不同
GET表示从服务器拿数据,POST表示往服务器提交数据传递数据的方式不同
GET传递数据,通常是通过query string把自定义数据交给服务器
(你去咖啡店买咖啡,对服务员说:“来杯拿铁,加冰,大杯。” 这里的 “拿铁、加冰、大杯” 就是你要传递的 “数据)
POST传递数据,通常是通过body把自定义数据交给服务器GET方法对应的请求,通常设计成"幂等”的
POST方法对应的请求,对于"幂等性"则无要求
(但是实际上,日常开发中,幂等不幂等更多的是看业务要求,和方法其实关系不大)承接幂等性
GET如果设计成幂等的,此时GET的结果是可以被缓存的
POST不涉及成幂等的,POST就不应该被缓存
GET 幂等 → 结果稳定 → 缓存能复用结果,提升速度。
POST 非幂等 → 结果会变 → 缓存会搞出 “假结果”,所以不能缓存。
(你用 POST /buy 提交 “买 1 瓶可乐”,服务器会减库存、扣钱。如果重复发这个请求,可能会多扣钱、多发货 —— 结果变了。
这时候要是用缓存,就会出问题:比如第一次买成功了,缓存记成 “成功”,第二次其实又买了一次,但缓存还拿上次的结果告诉你 “成功”,但实际已经多买了 —— 这就是 “假结果”。
所以 POST 不能缓存,每次都得让服务器重新处理,保证结果准确。) 幂等就是:不管操作执行 1 次还是 N 次,最终效果和结果都完全一样 。
开发里常用在接口设计(比如支付、删除、查询),保证重复调用不出幺蛾子~
5.4GET和POST理解的误解 POST 比 GET 更安全吗?
以登录为例,需要把用户名密码传递到服务器
POST登录,用户名密码是在body,从浏览器界面上是看不到的
GET登录,用户名密码是在url的querystring中,可能直接显示到浏览器地址栏的
此时就说明POST更安全吗?不一定
安全问题取决于是否加密以及加密算法的强度。这和将数据信息放到 query string 或 body 中无关,因为通过抓包,我们就可以得到这两部分的数据
GET只能传输文本数据吗?
GET只能传输文本,POST可以传输文本也能传输二进制这种说法是有误解的
URL 的 query string(就是 ?a=1&b=2 这部分)只能存文本
GET也能传二进制
1)先转码再拼接:基于query string,可以把二进制进行urlencode/base64转码
2)给get添加body:确保使用的库(客户端,服务器)都能支持这种用法即可
5.5其他方法
PUT和POST相似,只是具有幂等特性,一般用于更新DELETE删除服务器指定资源OPTIONS返回服务器所支持的请求方法HEAD类似于GET,只不过响应体不返回,只返回响应头TRACE回显服务器端收到的请求,测试的时候会用到这个CONNECT预留,暂无使用 这些方法的HTTP请求可以使用ajax来构造.(也可以通过一些第三方工具)
任何一个能进行网络编程的语言都可以构造HTTP请求.本质上就是通过TCPsocket写入一个符合HTTP协议规则的字符串。
6.认识请求报头"header" header的整体的格式也是"键值对"结构
每个键值对占一行,键和值之间使用分号分割
6.1HOST
告诉服务器 “我要访问哪个域名”
表示服务器主机的地址和端口
6.2Content-Length
告诉服务器 “请求体的字节长度是多少”
表示body中的数据长度,单位是字节. 告诉我们http数据报到哪里就结束了
6.3Content-Type
告诉服务器 “请求体的数据格式是什么”
表示请求的body中的数据格式
一个请求/响应中,没有body,也就没有这俩字段,如果有body则必须有Content-Length和Content-Type这两个字段
教务系统登陆界面
Content-Type中常见的类型
一、文本类(纯文字数据)
text/plain
最基础的纯文本,没有特殊格式,比如 “你好,世界” 这种字符串。
text/html
HTML 格式的文本,浏览器看到这个类型就知道要按网页格式解析(比如渲染
标题、
段落等)。
text/css
CSS 样式表文本,浏览器用它来给 HTML 加样式(比如颜色、布局)。
text/javascript (或 application/javascript)
JavaScript 代码,浏览器看到这个会执行里面的脚本(比如点击按钮的逻辑)。
二、表单类(网页表单提交的数据)
application/x-www-form-urlencoded
表单默认的提交格式,数据会被转成 key1=value1&key2=value2 这种字符串(比如登录时的用户名和密码,会被拼接成 username=xxx&password=xxx)。
注意:特殊字符会被 urlencode 编码(比如空格变 + 或 %20)。
multipart/form-data
用于表单上传文件或二进制数据(比如上传图片、文档)。数据会被分成多个 “块”,每个块带自己的标识,避免不同数据混在一起解析错误。
例:网页上传头像时,表单的 enctype 通常设为这个类型。
三、JSON 类(前后端常用的结构化数据)
application/json
JSON 格式的字符串,是前后端接口交互最常用的类型之一。比如 {"name":"张三","age":18} 这种键值对结构,几乎所有编程语言都能轻松解析。 6.4User-Agent
User-Agent简称UA,表示浏览器或操作系统的属性,相当于客户端(比如浏览器、手机 App、爬虫程序)给服务器发的一张 “身份证”,告诉服务器:“我是谁,我用的啥工具访问你”
让服务器知道访问者的 “身份信息”
比如你用的是 Chrome 浏览器还是 Safari 浏览器?
代码语言:javascript复制Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,like Gecko)其中Windows NT 10.0;Win64;x64表示操作系统信息
AppleWebKit/537.36 (KHTML,like Gecko) Chrome/91.0.4472.77
Safari/537.36表示浏览器信息.
作用:
辅助服务器适配内容:服务器通过解析User-Agent中的信息(如设备类型、操作系统、浏览器型号等),为不同客户端返回适配的内容
设备适配(移动端和PC端),浏览器适配,系统适配统计与分析:网站或服务器可通过收集User-Agent数据,统计用户的设备,浏览器,系统分布情况.例如:分析"60%用户使用Chrome浏览器,30%使用手机端Safari”,从而优化对应平台的兼容性。区分PC端和移动端6.5Referer 告诉服务器 “我从哪个页面跳过来的”。比如从百度搜索结果点进一个网页,服务器会收到 Referer: https://www.baidu.com,常用于统计流量来源。
Referer并不一定真的有,直接在地址栏输入url/点收藏夹就没有Referer
Referer是在HTTP请求中,发给服务器的,这个东西是给服务器使用的,
比如在搜狗页面搜索河北并跳转
6.6Cookie Cookie是什么?
Cookie是属于浏览器给网站提供的一种"客户端存储数据"机制
Cookie是浏览器本地持久化存储数据的一种机制.按照键值对方式存储,键值对的内容都是程序员自定义的.按照域名为维度分别进行存储。
最开始:浏览器和服务器 “素不相识”,浏览器里没有该网站的cookie 服务器发 “Set-Cookie”:给浏览器发 “小纸条”,响应头里加一个set-cookie
浏览器存 Cookie:把 “小纸条” 藏在本地,存到本地硬盘
再次访问:浏览器带着 Cookie “认亲”,自动把存好的cookie放到请求头里
出于安全考虑,浏览器禁止网页直接访问本地文件系统(避免访问不安全网站,导致硬盘中的数据受损)。不过浏览器并未完全封堵数据存储的可能性,而是提供了键值对形式的存储机制。这种存储方式的具体实现由浏览器内部封装完成,网页无法干预其底层存储过程。
服务器通过Set-Cookie响应头将键值对写入浏览器,首次访问网站时可能不带Cookie。之后浏览器访问该网站时就会自动携带这些Cookie信息。
Cookie从哪里来?
服务器返回的数据中,包含Set-Cookie字段(服务器这边的程序员根据需要,编写代码生成)
Cookie到哪里去?
后续浏览器访问同一个服务器的时候就会把之前存储的Cookie再带上,从而发送到服务器这边
举例登录Gitee
第一次登录访问服务器时无Cookie,访问成功后服务器返回set-cookie响应头,客户端收到cookie后就会存储到本地硬盘上,当再次访问服务器就会带上cookie
登陆成功之后,此时可以看到后续访问码云的其他页面(比如个人主页),请求中就都会带着刚才获取到的 Cookie信息
对于HTTP来说,针对同一个服务器,每次HTTP请求,彼此之前都是独立的
登录是前一个请求,后续的请求是如何知道我处于登录状态呢??
7. HTTP响应7.1状态码 状态码表示访问一个页面的结果(如访问成功、失败,还是其它一些情况等等),它是一个3位的整数,从 1xx、2xx、3xx、4xx、5xx,分为五个大类,每个大类的含义都不同。以下介绍一些常见的状态码及它的状态码解释
7.2 200 OK 表示访问成功
7.3 404 Not Found 没有找到资源;当在浏览器输入一个URL,该URL表示的资源不存在就会出现 404 Not Found
7.4 403 Forbidden 表示访问被拒绝,有的页面需要用户一定的权限才能访问,如查看码云私有的仓库
7.5 405 Method Not Allowed 表示访问的服务器不能支持请求中的方法或者不能使用该请求中的方法
7.6 500 Internal Server Error 表示服务器出现内部错误;一般是服务器的代码执行过程中遇到了一些特殊的情况,造成服务器崩溃可能会产生这个状态码
7.7 504 Gateway Timeout 表示当前服务器负载比较大,服务器处理单条请求的时耗很长,就会出现超时情况
7.8 302 Move temporarily 表示临时重定向
重定向相当于手机呼号的呼叫转移功能,如果我们换了一个手机号,就可以去办理该呼叫转移业务,使朋友拨打你的旧号码时,自动跳转到新号码
7.9 301 Moved Permanently 表示永久重定向,当浏览器收到这种响应时,后续的请求都会被自动改成新的地址
7.10 总结 状态码中2开头的,都是成功
4开头的,都是客户端这边出问题
5开头的,都是服务器端这边出问题
状态码范围类别(英文 / 中文)原因短语概括1XXInformational(信息性状态码)接收的请求正在处理2XXSuccess(成功状态码)请求正常处理完毕3XXRedirection(重定向状态码)需要进行附加操作以完成请求4XXClient Error(客户端错误状态码)服务器无法处理请求5XXServer Error(服务器错误状态码)服务器处理请求出错