HTTP学习
本文最后更新于 956 天前,其中的信息可能已经有所发展或是发生改变。

引言

这是在我阅读了肖佳老师的书《HTTP 抓包实战》后对 HTTP 相关内容的总结,主要还是报文相关 (记录:阅读此书与写出此文章耗时 5 天)

HTTP 协议报文的结构

HTTP 报文分 2 个:一个是 HTTP 请求报文,一个是 HTTP 响应报文

HTTP 请求报文 (Request)

HTTP 请求报文分为 3 个部分,第一部分叫起始行 (Request line),第二部分叫首部 (Request Header),第三部分叫主体 (Body)

  • 第一行中有 Method (请求方法)、URI 和协议版本。例如 GET https://blog.yexca.xyz/ HTTP/2
  • 第二部分是 Header (首部)
  • 第三部分是 Body (主体)

注意:Header 首部和 Body 主体之间有一个空行

HTTP 响应报文 (Responese)

HTTP 响应报文与请求报文的结构基本一样,也分为 3 个部分,第一部分叫响应行 (Response line),第二部分叫响应首部 (Response Header),第三部分是 0 主体 (Body)

  • 第一行有协议版本、状态码和状态码消息。例如 HTTP/2 200
  • 第二部分是 Header (首部)
  • 第三部分是 Body (主体)

注意:Header 首部和 Body 主体之间有一个空行

HTTP 协议请求方法和状态码

URL 格式

URL 的全称为 Uniform Reasource Locator,中文译名为统一资源定位符,用于完整地描述 Internet 上某一处资源的地址

URL 的基本格式如下:

schema://host[:port#]/path/.../[?query-string][#anchor]

属性描述
schema (协议) 指定底层使用的协议 (例如:http,https,ftp)
host (域名)HTTP 服务器的 IP 地址或者域名
port#(端口)HTTP 服务器的默认端口是 80, 这种情况下端口号可以省略。如果使用了别的端口,则必须指明
path (资源的路径) 访问资源的路径
query-string (参数) 发送给 HTTP 服务器的数据
anchor (锚) 锚,页面内部超链接

HTTP 请求方法

方法描述
1GET 请求指定的页面信息并返回实体主体
2HEAD 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头
3POST 向指定资源提交数据进行处理请求 (例如提交表单或者上传文件),数据被包含在请求体中。POST 请求可能会导致新的资源的建立和 / 或对已有资源的修改
4PUT 从客户端向服务器传送的数据取代指定文档的内容
5DELETE 请求服务器删除指定的页面

GET 与 POST 的区别

  1. GET 提交的数据会放在 URL 之后,以 ? 分隔 URL 和传输数据 (即 query-string,键值对方式),参数之间以 & 相连 而 POST 方法是把提交的数据放在 HTTP 包的 Body 中
  2. GET 提交的数据大小有限制 (因为浏览器对 URL 的长度有限制) 而 POST 方法提交的数据大小没有限制
  3. GET 方式需要使用 Request.QueryString 来取得变量的值 而 POST 方法通过 Request.Form 来获取变量的值

HTTP 状态码

HTTP 状态码存在于 HTTP 的响应报文中,其作用是 Web 服务器用来告诉客户端发生了什么事

HTTP 状态码被分为 5 大类,随着协议的发展,HTTP 规范中会定义更多的状态码吧

状态码已定义范围分类
1XX100~101 信息提示,表示请求已被成功接收,继续处理
2XX200~206 成功,表示请求已被成功接收、理解、接受
3XX300~305 重定向,要完成请求,必须进行进一步的处理
4XX400~415 客户端错误,请求有语法错误或请求无法实现
5XX500~505 服务器错误,服务器未能实现合法的请求

常见状态码

名称释义
200OK:服务器成功处理了请求
301/302Moved Permanently (重定向):请求的 URL 已移走。Response 中应该包含一个 Location URL,说明资源现在所处的位置
304Not Modified (未修改):客户端的缓存资源是最新的,需要客户端使用缓存
404Not Found:未找到资源
401 禁止访问
501Internal Server Error:服务器遇到一个错误,使其无法对请求提供服务

206 (Partial Content,部分内容)

206 状态码代表服务器已经成功处理了部分 GET 请求 (只有发送 GET 方法的 HTTP 请求,Web 服务器才可能返回 206)

应用比如说使用下载工具实现断点续传或者在线视频播放都是使用 206 状态码来实现

例如现在打开视频网站的一个视频,对于视频所在的 URL

  1. 浏览器会发送一个 GET 请求,Header 中包含 Range: bytes=5303296-5336063,意思就是请求得到 5303296-5336063 之间的数据
  2. Web 服务器返回一个 206 的 HTTP 响应。Header 中包含 Content-Range: bytes 5303296-5336063/12129376,表明这次返回的内容范围

301 与 302 (Moved Permanently,重定向)

在得到 301 或 302 响应后,浏览器会再次请求位于 Location 中返回新的 URL

状态码 301 和 302 在语法上是一模一样的,都是在 HTTP 响应的 Location 中返回新的 URL

区别在于:

  • 301 表示旧地址已经被永久移除了,这个资源不可访问了,搜索引擎会把权重算到新地址 例如:防止用户输错域名或更换域名
  • 302 表示旧地址的资源还在,仍然可以访问,这个重定向只是临时地从旧地址跳转到新地址,搜索引擎会把权重算到新地址 例如:未登录状态下访问需要登陆才能访问的页面

304 (Not Modified,未修改)

状态码 304 表示上次的文档已经被缓存了,还可以继续使用

400(Bad Request)

状态码 400 表示客户端请求有语法错误,发送的 HTTP 请求中的数据有错误,例如表单有错误或者 Cookie 有错误,不能被度武器所理解

401(Unauthorized)

状态码 401 是指为授权错误。有些网页采用的是 HTTP 基本认证 (Basic Authentication),需要在 HTTP 请求 Header 中带上 Authentication,否则服务器会返回状态码 401

404(Not Found)

该状态码表明服务器上无法找到请求的资源。除此之外,也可以在服务器端拒绝请求但不想说明理由时使用

例如 BV1AB4y1D7Ft 这个视频仅在登录并且收藏的情况下才可见,否则将返回 404

403(Forbidden)

状态码 403 表示 Web 客户端发送的请求被 Web 服务器拒绝了。如果服务器想说明为什么拒绝请求,可以在 Body 中描述原因。但这个状态码通常表示服务器不想说明拒绝原因

500(Internal Server Error)

状态码 500 代表服务器内部错误。出现错误的原因有很多,比如代码的错误、数据库连接语句出错、程序内部抛出异常、空指针错误等

503(Server Unavailable)

状态码 503 表示服务器暂时不可用。由于服务器维护或者过载,服务器目前无法处理请求

这个状况是临时的,并且将在一段时间以后恢复

了解全部状态码

访问:HTTP 状态码 | 菜鸟教程

HTTP 协议 Header

Header 的语法格式是 “key: value”,一行一个。每一个 Header 都有特殊的作用

Cache 相关的 Header

HTTP 请求与 HTTP 响应都有很多用于缓存的 Header。HTTP 缓存是指当 Web 请求抵达缓存时,如果本地有 “已缓存的” 副本,就可以从本地存储设备而不是原始服务器中获取该文件

Cookie 是一种 HTTP Cache,是 HTTP 中非常重要的内容。它由 key=value 的形式组成,比如 ip_country=CN

浏览器把 Cookie 通过 HTTP 请求中的 “Cookie: header” 发送给 Web 服务器,Web 服务器通过 HTTP 响应中的 “Set-Cookie: header” 把 Cookie 发送给浏览器

Accept

Accept 表示浏览器客户端可以接受的媒体类型。例如 Accept: text/html 代表可以接受服务器返回 html

通配符 * 代表任意类型,例如 Accept: text/html,\/*;q=0.8* 代表浏览器可以处理所有的类型。一般浏览器客户端给 Web 服务器发送的都是类似这个

Accept-Encoding

Accept-Encoding 跟压缩有关,浏览器发送 HTTP 请求告诉 Web 服务器浏览器支持的压缩形式,例如 Accept-Encoding: gzip, deflate

Accept-Language

Accept-Language 作用是声明自己接受的语言。注意语言与字符集的区别,中文是语言,中文有多种字符集,例如 GB2312、GBK 等。例如 Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4,zh-TW;q=0.2

User-Agent

User-Agent 的作用是浏览器用来告诉服务器,客户端使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等

例如 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:103.0) Gecko/20100101 Firefox/103.0 代表 64 位 Linux 系统,Firefox 是 103.0 版本

如果想要模拟各种不同的客户端,只要修改 User-Agent,就可以伪装成各种客户端

Referer

Referer 主要用来让服务器判断来源页面,即用户是从哪个页面来的,网站通常用其统计用户来源,也可以用作放盗链等

Connection

从 HTTP/1.1 起,系统默认都开启了 Connection: Keep-Alive,保持连接特性。Keep-Alive 不会永久保持连接,它有一个保持时间,可以在不同的服务器软件 (如 Apache) 中设定这个时间

Host

Host 的作用是指定被请求的主机和端口号,如果是 80 端口号会被自动隐藏

HTTP 协议中的缓存

缓存无处不在,有浏览器端的缓存、服务器端的缓存、代理服务器的缓存,还有 ASP.NET 页面的缓存、对象缓存、数据库缓存等等

HTTP 中具有缓存功能的是浏览器缓存和代理服务器缓存

HTTP 缓存是指当 Web 请求抵达缓存时,如果本地有 “已缓存的” 副本,就可以从本地存储设备而不是从原始服务器中提取这个文档

缓存的优点:减少了冗余的数据传输,节省了传输时间;减少了服务器的负担,大大提高了网站的性能;加快了客户端加载网页的速度等

如何判断缓存新鲜度

Web 服务器通过以下两种方式来判断浏览器缓存是否最新

  1. 浏览器把缓存文件的最后修改时间通过 HeaderIf-Modified-Since 告诉 Web 服务器。浏览器收到 HTTP 请求后,在 Header 中将文件最后修改世界 Last-Modified 与请求报文的 If-Modified-Since 相比较。若相同则说明文件是最新的,则发送状态吗 304 (Not Modified) 给浏览器客户端;若不同则发送状态码 200 把最新文件发送给浏览器客户端
  2. 浏览器把缓存文件的 ETag 通过 HeaderIf-None-Match 告诉 Web 服务器

与缓存有关的 Header

  • HTTP 请求报文 Header
名称释义
Cache-Control: max-age=0 以秒为单位
If-Modified-Since: Tue, 28 Jun 2022 00:50:56 GMT 缓存文件的最后修改时间
If-None-Match: “1771e0c387823da5329c20a76bece83c” 缓存文件的 ETag 值
Cache-Control: no-cache 不使用缓存
Pragma: no-cache 不使用缓存
  • HTTP 响应报文 Header
名称释义
Cache-Control: public 响应被缓存,并且可以被多用户访问使用
Cache-Control: private 响应只能作为私有缓存,特定用户使用
Cache-Control: no-cache 提醒浏览器要从服务器提取文档进行验证
Cache-Control: no-store 绝对禁止缓存 (用于机密、敏感文件)
Cache-Control: max-age=6060s 后缓存过期 (相对时间)
Date: Thu, 01 Sep 2022 21:56:36 GMT 当前响应发送的时间
Expires: Thu, 01 Sep 2022 21:57:37 GMT 缓存过期的时间 (绝对时间)
Last-Modified: Tue, 28 Jun 2022 00:50:56 GMT 服务端文件的最后修改时间
Etag: “1771e0c387823da5329c20a76bece83c” 服务器文件的 ETag 值

注:浏览器总是优先使用 cache-control,如果没有时才考虑 Expires

ETag

ETag 是 Entity Tag (实体标签) 的缩写,是根据实体内容生成的一段 hash 字符串 (类似于 MD5 或者 SHA1 之后的结果),可以表示文件的状态。当资源发生改变时,ETag 也随之发生改变

使用 ETag 主要是为了解决一些 Last-Modified 无法解决的问题,比如说某些服务器不能精确得到文件的最后修改时间、一些文件最后修改时间改变了但是内容不变、某些文件修改特别频繁甚至达到了以秒为单位以下等

注:Last-Modified 只能精确到秒

浏览器不使用缓存

使用 Ctrl+Shift+R 快捷键强制刷新浏览器,可以让浏览器不使用缓存,即浏览器的 HTTP 请求报文的 Header 中带有 Cache-Control: no-cache,明确告诉 Web 服务器不使用缓存

注:Pragma: no-cacheCache-Control: no-cache 作用相同,只是 Pragma: no-cache 是 HTTP/1.0 定义的,保留为了兼容性

直接使用缓存,不经过服务器验证

使用 Ctrl+R 快捷键刷新浏览器,浏览器会去 Web 服务器验证缓存

如果在地址栏直接输入地址并访问,浏览器会 “直接使用有效的缓存”,不会发送 HTTP 请求去服务器验证缓存,这种情况叫作缓存命中

公有缓存与私有缓存

公有缓存 Cache-Control: public 可以由多个用户共享访问,而私有缓存 Cache-Control: private 只能单个用户访问使用

HTTP 协议压缩和 URL Encode

HTTP 压缩是指 Web 服务器和浏览器之间压缩传输文本内容的方法。HTTP 采用通用的压缩算法,比如用 gzip 来压缩 HTML、JavaScript、CSS 文件

HTTP 内容编码与压缩的区别

在 HTTP 协议中,可以对 Body 部分进行编码,如可以采用 gzip 这样的编码,从而达到压缩的目地;也可以使用其他编码方式把内容搅乱或加密,以此来防止未被授权的第三方看到文档的内容。所以 HTTP 压缩其实就是 HTTP 内容编码的一种

HTTP 压缩的过程

  1. 浏览器发送 HTTP 请求 Header 中带 Accept-Encoding: gzip,deflate 告诉服务器浏览器支持 gzip 压缩
  2. Web 服务器接到 HTTP 请求后,先生成原始的 HTTP 响应,包含原始的 Content-TypeContent-Length;然后通过 gzip 对 HTTP 响应的 Body 进行编码,并在编码后 Header 中的 Content-TypeContent-Length 替换为压缩后的大小,以及加上编码方式 Content-Encoding: gzip;再把 HTTP 响应发送给浏览器
  3. 浏览器接到 HTTP 响应后,根据 Content-Encoding: gzip 来对 HTTP 响应进行解码,获取到原始 HTTP 响应后显示出网页

注:HTTP 请求也是可以编码的,但是浏览器一般不会对 HTTP 请求编码

内容编码类型

HTTP 定义了一些标准的内容编码类型,并允许用扩展的形式添加更多的编码

在 Header 中的 Content-Encoding 就是使用这些标准化的代号来说明编码时使用的算法

编码描述
gzip 表明实体采用 GNU zip 编码
compress 表明实体采用 UNIX 的文件压缩程序
deflate 表明实体是用 zlib 的格式压缩的
identity 表明没有对实体进行编码。当 Header 中没有 Content-Encoding 时,默认为此情况

gzip、compress 以及 deflate 编码都是无损压缩算法,用于减少传输报文的大小,不会导致信息缺失。其中 gzip 通常效率最高,使用最为广泛

深入理解 Cookie 机制

HTTP 协议是无状态的,对于浏览器的每一次请求,服务器都会独立处理,不与之前或之后的请求发生关联。即使是同一个浏览器发送了 3 个请求,服务器也会独立处理这 3 个请求,服务器并不知道这 3 个请求是来自同一个浏览器

会话机制与 Cookie 机制

服务器需要识别浏览器请求,就必须弄清楚浏览器的请求状态。既然 HTTP 协议是无状态的,那就让服务器和浏览器共同维护一个状态,这就是会话机制

  1. 浏览器第一次请求服务器时,服务器创建一个会话,并将会话 ID 作为响应的一部分发送给浏览器
  2. 浏览器存储会话 ID,并在后续请求中带上会话 ID
  3. 服务器取得请求中的会话 ID 就知道是不是同一个用户了

这样后续请求与第一次请求就产生了关联,而 Cookie 机制就是一种会话机制

服务器在内存中保存会话对象,浏览器可以使用 Cookie 机制保存会话 ID

Cookie 是什么

Cookie 是浏览器用来存储少量数据的一种机制,数据以 key=value 形式存储,多个 Cookie 之间以分号 ; 分隔,浏览器发送 HTTP 请求时自动附带 Cookie 信息

Cookie 最主要的作用是用来做用户认证,还可以用于保存用户的一些其他信息。也可以用于互联网精准广告定向技术,例如用户浏览了某些商品,就可以用 Cookie 记录下来,然后进行大数据深度分析,实现广告精准投放

鉴于此项,目前欧洲的一些国家已经对 Cookie 立法,并规定必须经过用户的允许才可以保存用户的 Cookie

Cookie 的属性

根据网站不同,Cookie 有所不同

  1. Expires

表示 Cookie 失效的时间,如果不指定则在关闭浏览器或页面时被浏览器删除

  1. Path

表示 Cookie 所属的路径,asp.net 默认为 / 也就是根目录

假设在同一个服务器上的目录如下:/test//test/cd//test/dd,Cookie1 的 Path 在 /test/,Cookie2 的在 /test/cd/,那么 /test/ 下的所有页面都可以访问到 Cookie1,而 /test/dd/ 的自页面不能访问 Cookie2. 因为 Cookie 只能让其 Path 路径下的页面访问

  1. HttpOnly

这是个关乎安全方面的属性,将一个 Cookie 设置为 HttpOnly 后,通过 JavaScript 脚本将无法读取到 Cookie 信息,这能有效防止用 XSS 发起攻击

一般来说,跟登录相关的 Cookie 必须设置为 HttpOnly

Cookie 的分类与位置

类别描述
会话 Cookie 临时的 Cookie,记录了用户访问站点时的设置与偏好 (例如访问本站时的 Cookie),关闭浏览器后将被删除
持久 Cookie 存储在硬盘上,有过期时间。不管退出浏览器还是重启计算机都存在

网站的自动登录就是储存持久 Cookie,在用户再次访问相同网站时会先在硬盘中查找相关 Cookie 然后放到 HTTP 请求报文中发送给服务器

那么持久 Cookie 存在计算机那里呢?不同浏览器会在各自的独立空间存放 Cookie,互不干扰

例如 Linux 下 Firefox 的 Cookie 位置:~/.mozilla/firefox/xxxxxxxx.default-release/cookies.sqlite

HTTP 基本认证

HTTP 协议是无状态的,浏览器和 Web 服务器之间可以通过 Cookie 来识别身份。那么一些桌面应用程序是如何跟 Web 服务器之间识别身份呢?

一些网站和 Web 服务使用的是 HTTP 基本认证。有些桌面应用程序 u 也通过 HTTP 协议跟 Web 服务器交互,桌面应用程序一般不使用 Cookie,而是把用户名 + 冒号 + 密码用 Base64 编码放在 HTTP 请求 Header 中的 Authorization 发送给服务端,这种方式叫 HTTP 基本认证 (Basic Authentication)

在基本认证中,Web 服务器可以拒绝一个事物,要求客户端提供有效的用户名和密码,服务器会返回 401 状态码来初始化认证质询,并用 WWW-Authenticate 响应首部指定要访问的安全域。浏览器收到质询时,会打开一个对话框请求用户输入用户名和密码,然后将用户名和密码用 Base64 编码,再用 Authorization 请求首部发送给服务器

一般家用路由器就是使用基本认证,RESTful API 就经常使用基本认证,使用命令 curl -u username:password URI 即可完成基本认证

HTTP 基本认证的缺点

  1. HTTP 协议是无状态的,同一个客户端对服务器的每个请求都需要认证
  2. Base64 编码是可逆的,非常容易破解,所以基本认证相当于以明文的方式传输用户名和密码。所以基本认证一定要用 HTTPS 加密传输,稍微安全一点
  3. 使用基本认证登录后,除非关闭浏览器或清除历史记录,否则无法登出。而 Cookie 机制的话,网站可以提供登出方式以使 Cookie 失效
  4. 无法防止重放攻击

摘要认证

摘要认证是针对基本认证存在的诸多问题而进行改良的方案。摘要认证是另一种 HTTP 认证协议,它试图修复基本认证的严重缺陷,进行如下改进

  1. 通过传递用户名、密码等计算出来的摘要来解决以明文方式在网络上发送密码的问题
  2. 通过服务器产生随机数 nonce 的方式防止恶意用户捕获并重放认证的握手过程
  3. 通过客户端产生随机数 cnonce 的方式支持客户端对服务器的认证
  4. 通过对内容也加入摘要计算的方式,可以有选择地防止对报文内容的篡改

参考文章

《图解 HTTP》读后总结及浅谈 – yexca|Hiyoung‘Blog

HTTP 状态码 | 菜鸟教程

IE/Firefox/Chrome 等浏览器保存 Cookie 的位置 – 脚本小娃子 – 博客园

“登录 “还是 “登陆 “? – 知乎

重放攻击 – 维基百科,自由的百科全书

通俗易懂:到底什么是 REST API?

表现层状态转换 – 维基百科,自由的百科全书

本文链接:HTTP学习
本文章由 yexca 采用 知识共享署名 - 非商业性使用 - 相同方式共享 4.0 国际许可协议 进行许可,转载请注明出处。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇