目录
http协议是应用层最广泛使用的协议之一,用来浏览器和web服务器之间的交互,它是浏览器和服务器交互的桥梁
HTTP 往往是基于传输层的 TCP 协议实现的. (HTTP1.0, HTTP1.1, HTTP2.0 均为TCP, HTTP3 基于 UDP 实现)
目前我们主要使用的还是 HTTP1.1 和 HTTP2.0 . 当前讨论的 HTTP 以 1.1 版本为主
当我们在浏览器中输入一个 "网址" (URL) 时, 浏览器就给服务器发送了一个 HTTP 请求, 服务器返回了一个 HTTP 响应. 这个响应结果被浏览器解析之后, 就展示成我们看到的页面内容. (这个过程中浏览器可能会给服务器发送 多个 HTTP 请求, 服务器会对应返回多个响应, 这些响应里就包含了页面 HTML, CSS, JavaScript, 图片, 字体等信息)
"超文本" 的含义, 就是传输的内容不仅仅是文本(比如 html, css 这个就是文本), 还可以是一些其他的资源, 比如图片视频音频等二进制的数据
使用fiddler抓包工具
HTTP 是一个文本格式的协议,要理解http交互的详细过程,可以借助第三方工具--fiddler来进行抓包,此工具专注于抓'http'使用起来更方便,没有其它的杂项
浏览器搜索fiddler下载安装,下载地址: https://www.telerik.com/download/fiddler
点击下载, 我们当前使用Classic版本,它是免费的
下载成功
安装
我们打开fiddler
fiddler本质是一个代理程序,使用的时候有两个注意事项
可能和别的代理程序冲突,使用时要关闭其它的代理程序(包括一些浏览器插件)
要想正确抓包,还需要开启https功能,https后续会介绍,是基于http的进化版本,当下互联网绝大部分的服务器都是使用https协议的,fiddler默认不能抓到https的包,需要手动启用一下https并且安装证书
如何开启https?
勾上这几个复选框,首次勾选会会弹出来对话框,询问你是否要安装对应的证书,选择是进行安装
证书相关的知识后续会介绍
理解代理
如何理解代理?
代理程序的代理就是再一次交互过程中,代理作为中间人,参与双方的交互,并且清楚的知道交互的过程都干了些什么事情,代理分为两种,正向代理和反向代理
正向代理代表着客户端的代理,反向代理代表着服务器端的代理
现在我们访问一个网站
看一下抓包结果,出现了https
这些结果就是浏览器访问百度时产生的http请求,浏览器打开一个页面,对应的http请求可能是一个,也可能是多个,我们最关注的是请求百度的首页页面,其它的请求都是基于这个请求产生的,也就是百度主页中的其它代码又产生了别的请求
这个圈起来的蓝色抓包结果是百度的主页页面,是html页面,绿色的是js.其他颜色的是反回数据
查看请求内容
如何查看请求内容?
我们双击请求列表中的选项,右侧就能查看到请求的详细情况
在右侧详细信息上方选择Raw,里面现实的是http最原始的效果.因为http请求是有一定格式的,fiddler会按照格式解析,呈现出不同的效果
点击右下角View in Notepad用记事本显示内容
抓包结果:
首行: [方法] + [url] + [版本]
Header: 请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分 结束
Body: 空行后面的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有 一个Content-Length属性来标识Body的长度;
观察抓包结果,可以看到,当前http请求,其实是一个行文本格式的数据,相比于tcp的二进制格式来说,更方便与用户来观察
再看看响应的数据,点击右下角的]Raw,用记事本查看
这些文本数据就是百度主页的html中的内容
可以看到响应数据也是文本,但是有的服务器会对响应进行压缩,也就是变成二进制乱码,压缩是为了节省带宽(带宽相比于cpu,内存,硬盘是最贵的)将数据压缩之后,文件体积就变小了,更容易进行传输,就像我们平常用的压缩包之类,虽然会花费一定的cpu资源进行解压缩,但是节省了大量的带宽!
如何理解压缩?
压缩的执行原理就是为了表达一个信息将数据进行重新编码,编码之后体积能减小,但是表达的含义是一样的,通过一些压缩算法,将这些html/js文本文件还是很容易压缩的..但是有的数据重新编码之后可能体积还更大了..
点击Raw上方的黄色框就可以进行手动解压缩,浏览器中会自动解压缩
抓包结果:
首行: [版本号] + [状态码] + [状态码解释]
Header: 请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分 结束
Body: 空行后面的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有 一个Content-Length属性来标识Body的长度; 如果服务器返回了一个html页面, 那么html页 面内容就是在body中.
总结:HTTP协议格式
有了上述基础,我们就可以研究http协议的协议格式了,学习一个协议就是学习它的报文格式
我们来看刚抓取的百度主页请求:
GET https://www.baidu.com/?tn=49055317_28_hao_pg HTTP/1.1
第一行称为首行 ,首行包含三个部分,之间通过空格来分开
GET:HTTP的方法(method)
https://www.baidu.com/?tn=49055317_28_hao_pg:URL
HTTP/1.1:版本号
首行=方法+URL+版本号
认识URL
平时我们俗称的 "网址" 其实就是说的 URL (Uniform Resource Locator 统一资源定位符).标识了互联网上的唯一资源的位置,资源在哪个服务器的哪个目录下的某个文件,是互联网上的具体地址
实际上,URL也可以起到身份标识的作用,可以视为一个URI ,开发中这两个词就混用了
看一个具体的URL
https : 协议方案名. 常见的有 http 和 https, 也有其他的类型. (例如访问 mysql 时用的 jdbc:mysql )
user:pass : 登陆信息. 现在的网站进行身份认证一般不再通过 URL 进行了. 一般都会省略
mp.csdn.net:服务器地址. 此处是一个 "域名", 域名会通过 DNS 系统解析成一个具体的 IP 地址. (通过 ping 命令可以看到, v.bitedu.vip 的真实 IP 地址为 118.24.113.28 )
使用 ping 命令查看域名对应的 IP 地址
在开始菜单中输入 cmd , 打开 命令提示符
在 cmd 中输入 ping v.bitedu.vip , 即可看到域名解析的结果.
端口号: 上面的 URL 中端口号被省略了. 当端口号省略的时候, 浏览器会根据协议类型自动决定使用 哪个端口. 例如 http 协议默认使用 80 端口, https 协议默认使用 443 端口
mp_blog/creation/editor:带层次的文件路径
not_checkout=1:查询字符串(query string). 本质是一个键值对结构. 键值对之间使用 & 分隔. 键和值之间使用 = 分隔.(query string 中的内容是键值对结构. 其中的 key 和 value 的取值和个数, 完全都是程序猿自己约定的. 我们可以通过这样的方式来自定制传输我们需要的信息给服务器.)
片段标识:此处省略了,片段标识主要用于页面内跳转,就是通过不同的片段标识跳转到页面内不同的章节
URL中可以省略的部分
协议名:省略后默认为http://
ip地址/域名:在 HTML 中可以省略(比如 img, link, script, a 标签的 src 或者 href 属性). 省略后表示服务器的 ip / 域名与当前 HTML 所属的 ip / 域名一致
端口号: 可以省略. 省略后如果是 http 协议, 端口号自动设为 80; 如果是 https 协议, 端口号自 动设为 443
带层次的文件路径: 可以省略. 省略后相当于 / . 有些服务器会在发现 / 路径的时候自动访问 /index.html
查询字符串: 可以省略
片段标识: 可以省略
URL encode
像/?:这样的字符已经被URL当作特殊意义理解了,因此不能随意出现,所以要将参数中的特殊字符进行转义,另外,一个中文字符由 UTF-8 或者 GBK 这样的编码方式构成, 虽然在 URL 中没有特殊含义, 但是仍然需 要进行转义. 否则浏览器可能把 UTF-8/GBK 编码中的某个字节当做 URL 中的特殊符号
转义的规则如下: 将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一 位,前面加上%,编码成%XY格式
例如:#被转义成了%23
认识method
实际开发中,这些方法大部分都是用不到的.最常见的就两个:GET和POST方法
GET方法
GET 是最常用的 HTTP 方法, 常用于获取服务器上的某个资源
在浏览器中直接输入 URL, 此时浏览器就会发送出一个 GET 请求. 另外, HTML 中的 link, img, script 等标签, 也会触发 GET 请求,后面我们会学习使用 JavaScript 中的 ajax 也能构造 GET 请求
打开 Fiddler, 访问百度, 观察抓包结果.
圈起来的Host是通过浏览器地址栏发送的 GET 请求,观察请求的详细结果
GET https://www.baidu.com/?tn=49055317_28_hao_pg HTTP/1.1Host: www.baidu.comConnection: keep-alivesec-ch-ua: "Google Chrome";v="111", "Not(A:Brand";v="8", "Chromium";v="111"sec-ch-ua-mobile: ?0sec-ch-ua-platform: "Windows"Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,**Origin: https://gitee.comSec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: https://gitee.com/dashboardAccept-Encoding: gzip, deflate, brAccept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6Cookie: user_locale=zh-CN; oschina_new_user=false; remote_way=http; sensorsdata2015jssdkchannel=%7B%22prop%22%3A%7B%22_sa_channel_landing_url%22%3A%22%22%7D%7D; yp_riddler_id=d8d10cbb-f305-47fb-af54-a7cbfef0cf1d; Serve_State=true; Hm_lvt_a1170d3ff94c236dacd36a05af8385ea=1677675596; slide_id=9; Hm_lvt_24f17767262929947cc3631f99bfd274=1678159247,1678270356,1678894764,1679221522; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%22186e5ed16381e1-093faf17633d508-7452547c-1327104-186e5ed16391b1%22%2C%22first_id%22%3A%22%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24latest_referrer%22%3A%22%22%7D%2C%22%24device_id%22%3A%221793b84d3f7525-07b3e1fef02c7-52301642-1327104-1793b84d3f89f7%22%2C%22identities%22%3A%22eyIkaWRlbnRpdHlfY29va2llX2lkIjoiMTg2YmExNWVkNjQ1ZTMtMGE1YmUxZjBiMDZkMDA4LTc0NTI1NDc2LTEzMjcxMDQtMTg2YmExNWVkNjUxNTAifQ%3D%3D%22%2C%22history_login_id%22%3A%7B%22name%22%3A%22%22%2C%22value%22%3A%22%22%7D%7D; csrf_token=wTR5jnS6NgxYG0E9vl4C%2BlB%2FqSNr9ZbLYI9TWpAiK%2B3giPoG8FWMXJSyG1ef%2FUsInsZoxjVNwwAZSNSZveL8yQ%3D%3D; user_return_to_0=%2Fdashboard; tz=Asia%2FShanghai; Hm_lpvt_24f17767262929947cc3631f99bfd274=1679221572; gitee_user=true; gitee-session-n=YzBNTGNnYkJ5Z0toa0dGajdPUGtEMmgrUzhnU0ZQQW9IRzYyYmoxUDFaQkFhc0thZVpsN0xMZjdhT1lXL2lFamduVmdFMzQ4SFBObm1Kb01qVVBIMnZDY251eUFpOW5mcWNoS2pva3N1bzJRdEtBdGc1ek5NbzhnbzdWV3dPVlpxdDdkYk1XZ3JUYktJUkQ0R2l5ckZLeU1iK0t4ZEJnei90VENTdVR6TlBxdTVIWUFBRGNRY3ZEYWswQVV6YjJKQStXUmdRbkZuWmZidlpLSndjbTNIWmx4OUNhYVBRZ290dGZtOWRLeTh1cmNzTXR1d2IyQVVJM3g2eE93aFBKMTdzN2pmSlh2NWRoaGxWZmlxME9BUjBTVE1rTzdlV1diYnRYUDhvY29vQTdRTUtIc1VYUzRxdU9QRWN0QVRUT09OSzQvb2tEbTVaVjBqRktBZU40SkhyR25Nb011SkkwYmt2QVNGblYwZ1k5VnQ1d1JFTm5ESmc3Tmg4bUFxMVN6dTVuZHRXeHBmMHZ1bVFLeFpGUHpsMlVucnhpZS9pcU8rYi9UTTRwOHI2VTk2RUxNTEx5bkdVN2VaWDlsWmp5LzlnNmozVDRsUlNvY1dqNkpKQnFBK05iMk9nLzZid01PcFlKb2dtVURqMFcxbGl6dm5CUng0MUIrYm9lVjJsdnRHUnhoVUlId1AwQ2JZVDh0K2VRVUNQNm9QVXZEbEJPUkRZVXV0Rm5WVFljPS0tdE1TZTJXTVFyZTQ5MXRkcFFWUkoxdz09--41f366131ccbf096e3466549fca18a1d27fae4e0{"query":"\n query unreadCount {\n current_user {\n unread_count {\n infos\n messages\n referer\n total\n }\n }\n}\n ","operationName":"unreadCount"}
POST 请求的特点
首行的第一部分为 POST
URL 的 query string 一般为空 (也可以不为空)
header 部分有若干个键值对结构.
body 部分一般不为空. body 内的数据格式通过 header 中的 Content-Type 指定. body 的长度由 header 中的 Content-Length 指定
经典面试题:POST和GET之间的典型区别
GET可以给服务器传递一些信息,传递的信息一般都放在query string中.POST传递信息是在body中
语义上的差别:GET请求一般用于从服务器获取数据,POST一般用于向服务器提交数据,比如上述访问页面就是向服务器获取信息,登录则是向服务器提交信息
GET通常会被设计成幂等的,POST不要求幂等(如果多次请求得到的结果一样, 就视为请求是幂等的,也即相同的输入,得到的结果是确定的)
GET 可以被缓存, POST 不能被缓存. (这一点也是承接幂等性)
补充:
GET和POST没有本质的区别,POST也完全可以设置成幂等的,GET用来提交数据,POST也可以获取数据
关于幂等性: 标准建议 GET 实现为幂等的. 实际开发中 GET 也不必完全遵守这个规则(主流网 站都有 "猜你喜欢" 功能, 会根据用户的历史行为实时更新现有的结果
POST与GET谁更安全的问题:
有的说法:如果使用GET进行登录请求,用户名密码通过query string可以看到,因此POST更安全.但是安全指的是如果数据被窃取,敏感信息不会泄露,就是安全的,安全的核心要素是加密,就算使用POST,抓包后也能获取http的详细信息,如果信息加密了,抓包后也不能获取原始信息
关于传输数据量: 有的资料上说 "GET 传输的数据量小, POST 传输数据量大". 这个是不科学 的, 标准没有规定GET的URL的长度, 也没有规定POST的body的长度. 传输数据量多少, 取决于不同浏览器和不同服务器之间的实现区别
关于传输数据类型: 有的资料上说GET只能传输文本数据,POST可以传输二进制数据,这个也是不科学的. GET的 query string 虽然无法直接传输二进制数据, 但是可以针对二进制数据 进行 url encode
其它方法
PUT 与 POST 相似,只是具有幂等特性,一般用于更新
DELETE 删除服务器指定资源
OPTIONS 返回服务器所支持的请求方法
HEAD 类似于GET,只不过响应体不返回,只返回响应头
TRACE 回显服务器端收到的请求,测试的时候会用到这个
CONNECT 预留,暂无使用
这些方法的 HTTP 请求可以使用 ajax 来构造或者使用第三方工具(postman等)
认识请求 "报头" (header)
header 的整体的格式也是 "键值对" 结构,每个键值对占一行.
键和值之间使用分号分割. 报头的种类有很多, 此处仅介绍几个常见的
我们登录gitte网站,然后从抓包,观察结果.
Host
表示服务器主机的地址和端口,这里的端口是
Host: nav-edge.smartscreen.microsoft.com
Content-Length
表示 body 中的数据长度
Content-Length: 1544
Content-Type
表示请求的 body 中的数据格式
可取的值是非常多的:
text/html
text/css
image/png
image/jpg
application/javascript
application/json
Content-Type: application/json; charset=utf-8
这里标识数据是json(一种数据格式) 格式,使用的字符集是utf8
body 格式形如:
{"username":"123456789","password":"xxxx","code":"jw7l","uuid":"d110a05ccde64b16a861fa2bddfdcd15"}
还有几种常见选项:
application/x-www-form-urlencoded: form 表单提交的数据格式. 此时 body 的格式形如:
title=test&content=hello
multipart/form-data: form 表单提交的数据格式(在 form 标签中加上 enctyped="multipart/form-data" . 通常用于提交图片/文件. body 格式形如:
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA------WebKitFormBoundaryrGKCBY7qhFd3TrwAContent-Disposition: form-data; name="text"title------WebKitFormBoundaryrGKCBY7qhFd3TrwAContent-Disposition: form-data; name="file"; filename="chrome.png"Content-Type: image/pngPNG ... content of chrome.png ...------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
User-Agent
(简称 UA) 表示浏览器/操作系统的属性
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.41
Windows NT 10.0; Win64; x64 表示操作系统信息
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.41表示浏览器信息
Referer 表示这个页面是从哪个页面跳转过来的(当前页面的来源),如果直接在浏览器中输入URL, 或者直接通过收藏夹访问页面时是没有 Referer 的
常见的用到的地方就是广告商的链接是按点击计费的,用户点击广告,此时就会跳转到对应的广告主的网站,广告主就给广告商打钱,具体被点击了多少次,需要双方共同统计,如果数据相差不大,就没有问题
http本身明文传输,很容易获取到请求的内容,也有办法篡改内容,本来是基于A网站的请求,refer被修改成另一个网站的请求了.这种现象叫做运营商劫持,利用这个漏洞,获得本应该属于A网站的利益.
由于运营商劫持太过分,于是各大网站都升级了https进行加密传输!
cookie
本质上是浏览器给网页提供的本地存储数据的机制
浏览器的代码为了保证安全性,是不被允许访问用户的本地硬盘的,但是我们有需要浏览器能在本地存储一定的数据
cookie对浏览器访问硬盘做出了明确的限制,保证了安全性,也能让浏览器在本地存储数据
cookie中存储了一个字符串, 这个数据可能是(网页客户端)自行通过 JS 写入的, 也可能来自于服务器(服务器在 HTTP 响应的 header 中通过 Set-Cookie 字段给浏览器返回数据)
是通过键值对区分的,键值对之间用分号分割.具体含义是程序员定义的
我们查看gitte的cookie
我们通过三个问题理解cookie
cookie是从哪来的?
cookie中的数据来自服务器.服务器会通过HTTP响应的报头部分(Set-Cookie 字段),服务器来决定浏览器的cookie要保存什么
cookie是存在哪里的?
可以认为cookie是存在于浏览器中的,存数据在硬盘上.cookie存在的时候,是按照浏览器+域名进行细分的
不同的浏览器各自存各自的cookie,同一个浏览器不同的域名对应不同的cookie
cookie里的内容不光是键值对,还会有一个过期时间,比如很多网站登陆一次后会自动记录登录状态.短期多次登录都不会重新登录.但是长时间不登陆就会重新登陆,这是因为cookie过期了,过期时间是可以设置的,相比于有金钱交易的网站,普通网站的cookie过期时间都比较长
cookie要到哪去?
cookie是要回到服务器的,一个服务器同一时刻是有很多客户端的,通过cookie来记录当前的客户端的中间状态,当客户端访问浏览器的时候,会自动把cookie的内容带入到请求中,服务器就知道客户端目前是什么状态了
认识请求 "正文" (body)
正文中的内容格式和 header 中的 Content-Type 密切相关, Content-Type描述了正文的内容,不同的 Content-Type就会有不同的正文格式. 上面也罗列了三种常见的情况.
下面可以通过抓包来观察这几种情况
1) application/x-www-form-urlencoded(上传文件时用到)
body是类似于键值对的方式组织,键值之间使用=连接,键值对之间使用&分割
2) multipart/form-data(上传文件时用到)
body中是以分割线开始,然后以分割线结束的
3) application/json(前后端交互非常常用的数据格式,我们后面也会经常用到)
最下方的正文格式就是json 格式
由于http协议十分重要并且内容也很多,此处就先介绍协议格式和http请求这两个内容,后续将会介绍http响应和如何构造http请求
来源地址:https://blog.csdn.net/chenchenchencl/article/details/129652090