后端开发必会计算机网络中的应用层协议 - HTTP/HTTPS

Java开发必会的应用层协议 - HTTP/HTTPS

1. HTTP的大概理解

1.1 HTTP的概念

HTTP 诞生与1991年. 目前已经发展为最主流使用的一种应用层协议 . 最新的 HTTP 3 版本也正在完善中, 目前

Google / Facebook 等公司的产品已经支持了. HTTP 往往是基于传输层的 TCP 协议实现的. (HTTP1.0,HTTP1.1, HTTP2.0 均为TCP , HTTP3 基于UDP 实现) 目前我们主要使用的还是 HTTP1.1 和HTTP2.0 . 当前课堂上讨论的 HTTP 以 1.1 版本为主.

HTTP采用一问一答模式 的协议,客户端发一个请求,服务器就返回一个响应,请求和响应一一对应。

我们平时打开一个网站, 就是通过 HTTP 协议来传输数据的. 当我们在浏览器中输入一个 搜狗搜索的 "网址" (URL) 时, 浏览器就给搜狗的服务器发送了一个 HTTP请求, 搜狗的服务器返回了一个 HTTP 响应

网络通信中也有其他的模型:多问一答 (主要用于上传大文件),一问多答 (下载大文件),多问多答(远程控制 eg.todesk)

1.2 HTTP的报文格式

为了学习HTTP的报文格式我们需要使用抓包工具Fidder,这是一种代理工具

下面我来解释一些代理

其中,我的助手就是正向代理,代表我(客户端)干活

1.2.1 抓包工具的原理

Fiddler 相当于一个 "代理".

浏览器访问 sogou.com 时, 就会把 HTTP 请求先发给 Fiddler, Fiddler 再把请求转发给 sogou 的服务器. 当 sogou 服务器返回数据时, Fiddler 拿到返回数据, 再把数据交给浏览器. 因此 Fiddler 对于浏览器和 sogou 服务器之间交互的数据细节, 都是非常清楚的.

1.2.2 抓包结果

HTTP请求报文格式

HTTP响应报文格式

HTTP文本请求/响应协议格式总结:

2. 针对抓包结果分析每一部分

2.1 URL

url可以描述网络上的唯一资源所在位置

如果大家学过jdbc,一定见过 JDBC 连接 MySQL 数据库的 URL 字符串

java 复制代码
jdbc:mysql://127.0.0.1:3306/java113?characterEncoding=utf8&useSSL=false

下面我们对于这个字符串进行分析

我们再来看一个访问搜狗服务器的url

2.2 URL encode

像 / ? : 等这样的字符, 已经被url当做特殊意义理解了. 因此这些字符不能随意出现.

比如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义.

进行转义的目的

一个中文字符由 UTF-8 或者 GBK 这样的编码方式构成, 虽然在 URL 中没有特殊含义, 但是仍然需要进行转义. 否则浏览器可能把 UTF-8/GBK 编码中的某个字节当做 URL 中的特殊符号

我们可以利用UrlEncode编码工具进行对于字符的转义

ulrencode把数据的二进制内容,每个字节取出来,用16进制表示,前面加上%(1Byte=8bit=2个16进制数)

因此+转义之后的结果是=>%2b

2.3 认识 "方法" (method)

即这次请求要干什么

其中GET和POST这两个就是最常见的请求,其中

GET一般用来获取html,获取css,获取js等操作

POST一般用来上传文件

2.3.1 GET 方法

GET 是最常用的 HTTP 方法. 常用于获取服务器上的某个资源.

在浏览器中直接输入 URL, 此时浏览器就会发送出一个 GET 请求.

另外, HTML 中的 link, img, script 等标签, 也会触发 GET 请求

用fiddler捕获的css页面

用fiddler捕获的js页面

GET 请求的特点

• 首行的第一部分为 GET

• URL 的 query string 可以为空, 也可以不为空.

• header 部分有若干个键值对结构.

• body 部分为空.

2.3.2 POST 方法

POST 方法也是一种常见的方法. 多用于提交用户输入的数据给服务器(例如登陆页面).

通过 HTML 中的 form 标签可以构造 POST 请求, 或者使用 JavaScript 的 ajax 也可以构造 POST 请求

eg. 这是向山东大学信息化公共服务平台(service.sdu.edu.cn)发起的同域 AJAX 异步 HTTP POST

请求,目标接口为/tp_up/up/subgroup/getUsedAppsList,核心用于获取用户已使用的应用列表,请求格式规范且为同域合法请求

POST 请求的特点

• 首行的第一部分为 POST

• URL 的 query string 一般为空 (也可以不为空)

• header 部分有若干个键值对结构.

• body 部分一般不为空. body 内的数据格式通过 header 中的Content-Type 指定. body 的长度由 header 中的 Content-Length 指定.

经典面试题: 谈谈 GET 和 POST 的区别

  1. 语义不同 : GET 一般用于获取 数据, POST 一般用于提交数据.

  2. GET 的 body 一般为空, 需要传递的数据通过 query string 传递 , POST 的 query string 一般为空, 需要传递的数据通过 body 传递

  3. GET 请求一般是幂等的, POST 请求一般是不幂等的. (如果多次请求得到的结果一样, 就视为请求是幂等的).

    比如:查余额(GET),查 1 次和查 100 次,余额不会变,也不会产生新数据 → 幂等; 比如:下单付款(POST),点 1次是正常下单,点 10 次可能扣 10 次钱 → 不幂等。

  4. GET 可以被缓存, POST 不能被缓存. (这一点也是承接幂等性).

    缓存只适合 "只读、无副作用" 的请求,因为 GET 是幂等的(只读、不修改数据),缓存它的结果是安全的。否则会出大问题,因为 POST 是不幂等的(修改数据、有副作用),缓存它的结果会导致严重错误

    反例(如果缓存 POST ): 你发 POST /order 创建订单 → 服务器返回 "订单创建成功(订单号 1001)" →浏览器缓存这个结果; 你不小心刷新页面(再次发同样的 POST),浏览器直接返回缓存的 "订单 1001",但服务器其实又创建了订单1002 → 你看到的是 "订单 1001",但服务器里多了订单 1002,数据不一致

关于一些网上常见说法的讨论:

特性 GET 请求 POST 请求 结论
传输文本 ✅ 可行 (短文本) ✅ 可行 (长文本/复杂格式) 两者皆可,POST 更优
传输二进制 ⚠️ 理论可行,实际禁用 ✅ 标准方案 只能用 POST

2.3.3 其他操作:

这四个操作中的任何一个都能实现增删改查,其实完全取决于代码怎么写

2.4 请求报头(header)的关键属性

bash 复制代码
GET https://gitee.com/HGtz2222 HTTP/1.1
Host: gitee.com
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/w
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
sec-ch-ua-mobile: ?0
Referer: https://gitee.com/login
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: oschina_new_user=false; user_locale=zh-CN; yp_riddler_id=1ce4a551-a160-4

header 的整体的格式也是 "键值对" 结构.

每个键值对占一行. 键和值之间使用分号分割.

Host

表示服务器主机的地址和端口.

Content-Length

表示 body 中的数据长度

Content-Type

表示请求的 body 中的数据格式.

如果报文有 body 却缺少这两个报头(Content-Length和Content-Type)中的任意一个,就会被视为非法或错误的 HTTP 报文,因为接收方无法知道 body 的长度和格式,也就无法正确解析。

User-Agent (简称 UA)

表示浏览器/操作系统的属性. 形如:

java 复制代码
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) 表示浏览器信息.

UA的作用:根据用户使用的设备,进行区分,通过UA中浏览器/操作系统版本,区分出当前用户的设备,支持个性化的体验,比如:前端有响应式编程一说,通过CSS中的媒体查询功能,感知到当前的窗口尺寸,通过不同的尺寸,设置不同样式,一个页面,就可以适配不同的窗口

Referer

表示这个页面是从哪个页面跳转过来的. 形如

java 复制代码
 https://www.doubao.com/login

如果直接在浏览器中输入URL, 或者直接通过收藏夹访问页面时是没有 Referer 的.

Cookie

设计Cookie的目的,既满足网页 "保存本地数据" 的开发需求,又通过浏览器的管控,避免 JS 直接操作文件系统带来的安全风险(如恶意篡改用户文件)。

Cookie 中存储了一个字符串, 这个数据可能是客户端(网页)自行通过 JS 写入的, 也可能来自于服务器(服务器在 HTTP 响应的 header 中通过 Set-Cookie 字段给浏览器返回数据).往往可以通过这个字段实现 身份标识 的功能.

HTTP 协议本身是无状态的(服务器记不住每次请求的用户身份),Cookie 会存储服务器颁发的会话标识(如 JSESSIONID、Token)。用户后续访问网站时,浏览器会自动将 Cookie 带入请求头,服务器通过标识识别用户,实现 一次登录,全程免登

用户使用浏览器访问服务器过程

注意:

  1. Session 是服务器端 的一个对象,用于存储当前用户会话的详细信息(如用户 ID、用户名、权限等)。session可以让服务器 "记住" 用户,避免每次请求都需要重新验证身份。
  2. Session 的完整工作流程

2.5 HTTP 协议基于 TCP 传输时的报文结构、边界划分

  1. HTTP 报文的结构(基于 TCP)
    HTTP 协议本质上是把字符串按约定格式组织起来,通过 TCP socket 传输,完整结构分为 4 部分:
    首行 :包含请求方法、URL、HTTP 版本号
    请求头 :多行键值对,描述请求的元信息(如 Host、Content-Type 等)
    空行 :作为请求头和正文的分隔符
    正文(body):承载业务数据(如 JSON、表单、文件等),可选
  2. TCP 上如何划分 HTTP 请求的边界
    TCP 是面向字节流 的协议,一个连接上可以传输多个 HTTP 请求,服务器需要明确每个请求的起止位置
    无 body 的请求:读到空行,就认为请求结束
    有 body 的请求:先读取首行和请求头,读到空行后,解析 Content-Length 头,再读取对应字节数的正文,以此确定请求结束
  3. UDP 的特点(与 TCP 对比)
    UDP 是面向数据报的协议,和 TCP 的字节流模式有本质区别:
    读写的基本单位是 UDP 数据报
    一个 UDP 数据报就对应一个完整的应用层数据包
    调用一次 receive 操作,就能得到一个明确的 UDP 数据包,无需额外划分边界

3. HTTP 响应详解

认识 "状态码" (status code)

状态码表示访问一个页面的结果. (是访问成功, 还是失败, 还是其他的一些情况...).

以下为常见的状态码.

3.1 200 OK

这是一个最常见的状态码, 表示访问成功,我们打开fidder,几乎都是200

注意: 在抓包观察响应数据的时候, 可能会看到压缩之后的数据, 形如:

网络传输中 "带宽" 是一个稀缺资源, 为了传输效率更高往往会对数据进行压缩.

点击 Fiddler 中的,

即可进行解压缩, 看到原始的内容.

3.2 404 Not Found

没有找到资源.

浏览器输入一个 URL, 目的就是为了访问对方服务器上的一个资源. 如果这个 URL 标识的资源不存在,那么就会出现 404

例如, 在浏览器中输入 www.sogou.com/index.html , 此时就在尝试访问 sogou 上的

/index.html 这个资源.如果输入正确, 则可以正确访问到. 但是如果输入错误, 比如www.sogou.com/index2.html , 就会看到 404 这样的响应.

bash 复制代码
HTTP/1.1 404 Not Found
Server: nginx
Date: Mon, 09 Mar 2026 02:38:57 GMT
Content-Type: text/html
Connection: keep-alive
Vary: Accept-Encoding
Content-Length: 564

<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->

3.3 403 Forbidden

表示访问被拒绝. 有的页面通常需要用户具有一定的权限才能访问(登陆后才能访问). 如果用户没有登陆,直接访问, 就容易见到 403.

例如: 查看码云的私有仓库, 如果不登陆, 就会出现 403. 参考链接:
https://gitee.com/HGtz2222/blog_python

3.4 405 Method Not Allowed

请求的方法和服务器这边声明的注解不匹配,就会出现405

3.5 500 Internal Server Error

服务器出现错误,服务器处理逻辑的代码中抛出异常,但是写代码时候没有catch到

3.6 504 Gateway Timeout

当服务器负载比较大的时候, 服务器处理单条请求的时候消耗的时间就会很长, 就可能会导致出现超时的情况. 这种情况在双十一等 "秒杀" 场景中容易出现, 平时不太容易见到

3.7 302 Move temporarily

重定向,访问服务器A,服务器A告诉你去找B,某个网站如果想要修改域名,如果直接把服务器架设在新的域名上,不采取其他操作的话,原来的用户无法通过原来的域名进行访问。还有一种办法就是可以把服务器架设在新的域名上,同时,给旧域名设置重定向,可以重定向到新域名。这样用户既可以访问旧的域名,也可以访问新的域名。

3.8 状态码的总结

4. HTTPS

4.1 HTTP的缺点

用户想要访问服务器下载某app,可是过程中可能会路过被黑客入侵的服务器,此时黑客可以对于用户访问/服务器返回的数据进行篡改,非常的不安全

4.2 HTTPS的概念

HTTPS 也是一个应用层协议. 是在 HTTP 协议的基础上引入了一个加密层. HTTP 协议内容都是按照文本的方式明文传输的. 这就导致在传输过程中出现一些被篡改的情况.

4.3 HTTPS 的工作过程

既然要保证数据安全, 就需要进行 "加密".

网络传输中不再直接传输明文了, 而是加密之后的 "密文".

加密的方式有很多, 但是整体可以分成两大类: 对称加密 和 非对称加密。

4.3.1 引入对称加密

对称加密其实就是通过同一个 密钥 , 把明文加密成密文, 并且也能把密文解密成明文 .

但是如果直接把密钥明文传输, 那么黑客也就能获得密钥了~~ 此时后续的加密操作就形同虚设了.

但是要想对密钥进行对称加密, 就仍然需要先协商确定一个 "密钥的密钥". 但是问题是:总得由一个密钥是需要明文传输的. 此时密钥的传输再用对称加密就行不通了.

就需要引入非对称加密.

4.3.2 引入非对称加密

非对称加密要用到两个密钥, 一个叫做 公钥 , 一个叫做 私钥 .

公钥和私钥是配对的. 最大的缺点就是运算速度非常慢,比对称加密要慢很多 .

• 通过公钥对明文加密, 变成密文

• 通过私钥对密文解密, 变成明文

也可以反着用

• 通过私钥对明文加密, 变成密文

• 通过公钥对密文解密, 变成明文

下面我们这样使用,把公钥当成锁,把私钥当成钥匙

客户端将密文使用公钥加密之后,传输给服务器,由于黑客没有私钥,无法解密,服务器返回响应。之后客户端的密文请求采用对称加密(此时使用对称加密没有问题,因为,黑客侵入的路由器没有私钥无法解密)

当前的场景有三个密钥:

  1. 客户端生成的对称密钥
  2. 服务器生成的公钥,可以给所有设备告知
  3. 服务器生成的私钥,只有自己知道

虽然理论上,客户端持有公钥,服务器持有公钥和私钥,然而在第一次访问一个陌生网站时,客户端一开始本身没有公钥,这个公钥也要从服务器获取的,就会出现以下重大安全隐患:

  1. 客户端向服务器询问公钥pub1,服务器返回pub1,被黑客获取pub1.
  2. 黑客不直接转发pub1,而是告诉客户端公钥是pub2(黑客自己生成一对非对称密钥,包括公钥pub2,私钥pri2),以后客户端就会用pub2进行加密。
  3. 当客户端向服务器发送以后要使用的对称密钥key(对称密钥由客户端生成)时,客户端在发送之前也会使用pub2进行加密,然后向服务器发送数据
  4. 此时,当该数据经过黑客入侵的路由器时,黑客会使用自己的私钥pri2进行解密,获得对称密钥key,然后使用之前获得的pub1进行加密,传送给服务器
  5. 之后,客户端传输给服务器的数据以及服务器传输给客户端的数据也会使用key进行加密,黑客就可以使用对称密钥key进行解密,获取机密信息了

要想彻底解决这个问题,需要引入证书

4.3.3 引入证书

从刚才的例子,我们知道问题出在客户端无法识别黑客伪造的pub2是错误的公钥,如果能识别出来,则问题可以得到解决。

引入证书之后,服务端在使用HTTPS前,需要向CA机构申领一份数字证书,数字证书里含有证书申请者信息、公钥信息等。服务器把证书传输给浏览器,浏览器从证书里获取公钥就行了,证书就如身份证,证明服务端公钥的权威性。

4.3.3.1 分工

我们先讲一下分工
服务器 :持有自身的非对称密钥对(pub1 公钥、pri1 私钥),需要申请合法证书证明 pub1 的身份。
第三方认证机构 (CA):公认的可信组织,持有自身的非对称密钥对(pub2 公钥、pri2 私钥),pub2 会预装在所有正规操作系统 / 浏览器中
客户端:自身持有pub2,可以通过验证 CA 签名,确认服务器公钥的真实性

4.3.3.2 阶段 1:服务器向 CA 申请数字证书(线下 / 前置操作)

服务器 搭建完成后,需向 CA 申请证书,仅需申请一次,后续长期保存使用 :

提交材料:服务器向 CA 提交核心信息,包括自身公钥 pub1、服务器域名、持有者信息、证书有效期等

阶段1:CA 生成证书 (核心签名流程):

步骤 1(生成校验和 ):CA 将服务器提交的核心信息,通过哈希算法(如 SHA256)计算出一个固定长度的校验和(类似 "数据指纹")。

步骤 2(加密签名):CA 使用自己的私钥 pri2 ,对这个校验和进行加密 ,生成数字签名。

步骤 3(封装证书):将服务器原始信息、CA 数字签名、CA 公钥标识等内容封装,形成最终的数字证书,下发给服务器。

阶段 2:证书分发 (客户端请求证书,防范中间人拦截)

客户端发起请求:客户端向服务器发送 "大哥大哥,咱的证书是啥?",请求获取服务器证书。

黑客拦截尝试:黑客(入侵路由器)拦截该请求,同时也向服务器转发请求,拿到服务器的真实证书。

黑客伪造失败:黑客试图用自己的公钥伪造证书,但因没有 CA 的私钥 pri2,无法生成合法的数字签名,只能转发服务器的真实证书给客户端(伪造证书会被后续验证直接拦截)。

阶段 3:客户端验证证书 (核心安全环节,对应图中 3 步校验)

客户端收到证书后,通过3 步校验确认证书合法性,核心是利用系统内置的 CA 公钥 pub2 验证签名

  1. 校验证书基础字段:先检查证书的颁布机构是否可信、有效期是否过期、域名是否与当前访问的服务器一致(基础合法性筛查)。
  2. 双重计算校验和 (核心验签):
    a. 计算校验和 1客户端提取证书中的服务器原始信息 ,用与 CA 相同的哈希算法,重新计算出一个校验和
    b. 解密校验和 2:客户端使用系统内置的 CA 公钥 pub2,对证书中的CA 数字签名进行解密,得到 CA 当初生成的原始校验和。
  3. 对比校验,判定结果:
    验证通过:若校验和 1 = 校验和 2,说明证书未被篡改服务器的公钥 pub1 是真实合法的。
    验证失败:若两者不一致,说明证书被黑客篡改(或为伪造证书),客户端立即终止通信,弹出 "不安全连接" 警告。
  4. 如果验证通过,当客户端向服务器传输自己生成的对称密钥key之前,会使用pub1进行加密,黑客由于没有pri1,所以无法解密。服务器得到对称密钥key,之后客户端服务器的通信使用key进行通信,由于黑客无对称密钥key,仍然无法解密,所以是安全的。

4.4 HTTPS面试考点总结

相关推荐
周淳APP3 小时前
【HTTP相关及RESTful】风萧萧兮易水寒之壮士学习不复返
前端·javascript·网络·网络协议·http·restful·jsonp
萝卜白菜。3 小时前
http头Location是相对路径还是绝对路径
网络·网络协议·http
鸽鸽程序猿3 小时前
【JavaEE】【SpringAI】聊天模型
java·java-ee
森叶3 小时前
AI 时代的“万能插座”:深度拆解 MCP 协议背后的 HTTP + SSE 异步架构(含完整、可直接运行源码 + 逐行注释)
人工智能·http·架构
韭菜张师傅3 小时前
Ceph环境完全重置指南:彻底清理集群环境
java·网络·ceph
SunnyDays10113 小时前
使用 Java 实现 Word 文档水印自动化(全面指南)
java·添加水印·word文档
周淳APP3 小时前
【计算机网络之HTTP、TCP、UDP、HTTPS、Socket网络连接】
前端·javascript·网络·网络协议·http·前端框架
敲代码的小王!3 小时前
prompt开发游戏-哄哄模拟器
java·游戏·ai·prompt
学编程就要猛3 小时前
JavaEE:多线程初阶
java·开发语言·jvm
博语小屋3 小时前
HTTP详解
网络·网络协议·http