Skip to content

网络协议

常见的 HTTP Code

  • 1XX - 服务器已收到请求,正在处理,但还未完成
  • 2XX - 请求成功,服务器已成功返回数据
  • 3XX - 需要客户端采取进一步操作(如跳转)
  • 4XX - 客户端请求错误,服务器无法处理
  • 5XX - 服务器内部出错,无法完成请求

HTTP2 的优点

  • 多路复用:在单一连接上并行处理多个请求,减少延迟。
  • 头部压缩:减少冗余的请求头和响应头,提高带宽利用率。
  • 服务器推送:允许服务器主动推送资源,减少客户端的请求次数。
  • 连接复用:减少 TCP 连接的开销。
  • 优先级控制:允许客户端设置请求的优先级,更高效地加载资源。
  • 低延迟:提高了响应速度,减少了加载时间。
  • 二进制协议:提高了协议的效率和灵活性。

简述 TCP 连接的过程

中间人攻击

中间人攻击(Man-in-the-Middle Attack,简称 MITM) 是一种网络攻击方式,攻击者通过窃取或篡改通信双方之间的数据,从而破坏或伪造通信内容。在这种攻击中,攻击者充当通信双方之间的“中间人”,获取、修改、转发或伪造消息,通常在用户和服务之间的通信过程中悄无声息地进行

反向代理与正向代理

反向代理是指代理服务器代表目标服务器接收客户端的请求,然后将请求转发到一个或多个目标服务器。客户端并不知道自己正在与代理服务器通信,而是以为它直接在与目标服务器交互。比如负载均衡

正向代理是客户端和目标服务器之间的中间服务器,通常由客户端配置,客户端将自己的请求转发给代理服务器,再由代理服务器转发给目标服务器。反过来,目标服务器的响应也会通过代理服务器返回给客户端。比如科学上网

简述单点登录

文件上传如何做断点续传

断点续传主要通过将文件分成多个小块(称为 分片)进行上传。每个分片在上传过程中都被单独处理,上传失败时,只需要重新上传失败的分片,而不需要从头开始上传整个文件。

断点续传的基本步骤如下:

  • 客户端将文件分块: 将大文件拆分成多个小块,每个块的大小可以根据需求配置,通常每块的大小会在几 MB 到几十 MB 之间。分块上传的方式有助于在上传过程中实现断点续传。

  • 上传过程中记录上传状态: 在上传时,客户端需要记录每个块是否上传成功,通常会在客户端本地或服务器端记录每个块的上传状态。常见做法是将每个分片的上传进度保存在数据库或临时文件中。

  • 断点续传: 如果上传过程中的网络中断或发生其他异常,客户端会根据已上传的分块信息,继续上传未上传的分块,而不需要重新上传已成功上传的部分。

  • 服务器端合并文件: 当所有的分片都上传完成后,服务器会将这些小块按照顺序重新拼接成原始文件,完成文件的上传过程。

介绍 SSL 和 TLS

说说网络的五层模型

应用层 (Application Layer) <- 用户与应用交互

传输层 (Transport Layer) <- 提供端到端的数据传输服务

网络层 (Network Layer) <- 处理数据包的路由与寻址

数据链路层 (Data Link Layer) <- 在局部网络上传输数据帧

物理层 (Physical Layer) <- 在物理介质上传输比特流

GET 和 POST 的区别

GETPOST 都是 HTTP 请求方法,用于客户端和服务器之间的数据传输,它们在使用上有一些关键的区别。下面是 GET 和 POST 的主要区别:

1. 目的和用途

  • GET:主要用于从服务器获取数据。请求的数据通常附带在 URL 中。
  • POST:主要用于向服务器发送数据,通常用于提交表单或上传文件,数据通常包含在请求体中。

2. 数据传输方式

  • GET:数据作为查询字符串附加在 URL 后面,形式为 key=value 键值对,多个参数用 & 连接。例如:http://example.com?name=John&age=30
  • POST:数据被包含在请求体(body)中,不显示在 URL 中,因此适合传输较大或较敏感的数据。

3. 数据长度限制

  • GET:由于数据被放在 URL 中,URL 的长度受到浏览器和服务器的限制。不同的浏览器和服务器对 URL 长度的限制不同,一般是 2048 字符。
  • POST:没有明确的长度限制,理论上可以发送非常大的数据量(限制通常由服务器配置决定)。

4. 安全性

  • GET:由于数据作为查询参数附加在 URL 中,因此数据在传输过程中容易被他人窥探。尤其对于敏感信息(如用户名、密码),使用 GET 并不安全。
  • POST:虽然数据放在请求体中,URL 中不直接显示,因此相对 GET 更加安全。特别是对于敏感数据,POST 更合适,但它并不意味着数据是加密的(除非使用 HTTPS)。

5. 缓存与书签

  • GET:由于 GET 请求的参数是附加在 URL 中的,浏览器可以缓存 GET 请求的结果,并且可以通过 URL 直接书签(例如,保存网址)。
  • POST:POST 请求的结果不会被缓存,也不能通过 URL 直接书签。每次提交 POST 请求都会发起新的请求。

6. 幂等性

  • GET:GET 请求是幂等的(Idempotent),即同样的请求可以重复多次,结果不会改变。GET 请求应仅用于获取数据,不应对服务器状态造成任何改变。
  • POST:POST 请求是非幂等的,每次提交 POST 请求都可能会导致不同的结果(例如,提交表单数据可能会导致数据库内容发生变化)。

HTTP 劫持、DNS 劫持与 XSS

怎样解决跨域问题?

  • CORS(跨源资源共享)在服务器端设置 HTTP 头来允许跨域请求
  • JSONP(JSON with Padding)是一种通过标签加载资源的方式,利用 script 标签不受同源策略的限制来绕过跨域。JSONP 只支持 GET 请求,不支持其他类型的 HTTP 请求
  • 通过设置代理服务器来中转请求,将跨域请求发送到自己控制的服务器,再由该服务器请求目标资源,获取到数据后返回给客户端。这样可以避免跨域问题,因为浏览器并不会直接向目标服务器发送请求
  • WebSocket 是一种双向通信协议,不受同源策略的限制。可以通过 WebSocket 实现跨域通信,尤其适用于需要实时数据交换的场景

简单请求&预检请求

跨域资源共享(CORS) 机制中,浏览器会根据请求的 类型头信息 采取不同的处理方式,主要分为 简单请求(Simple Request)预检请求(Preflight Request)

🚀 1. 什么是简单请求(Simple Request)?

简单请求符合特定条件 的跨域 HTTP 请求,浏览器不会发起预检请求,直接发送请求并接受响应。

📌 简单请求的条件

浏览器只会将满足 以下三个条件 的请求视为 简单请求

  1. 请求方法 只能是以下三种之一:
    • GET
    • POST
    • HEAD
  2. 请求头 只能包含以下字段(不能自定义额外的 Header):
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type(但仅限于 application/x-www-form-urlencodedmultipart/form-datatext/plain
  3. 请求体 格式受限:
    • application/json 不属于简单请求,因为 application/json 不在 Content-Type 允许的范围内。

🛠 简单请求示例

javascript
fetch("https://api.example.com/data", {
  method: "GET",
  headers: {
    Accept: "application/json",
  },
})
  .then((response) => response.json())
  .then((data) => console.log(data));

请求不会触发预检,直接发送!
✅ 服务器 必须 在响应头中返回 Access-Control-Allow-Origin,否则浏览器会阻止访问。

🎯 服务器响应示例

http
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/json

🔥 2. 什么是预检请求(Preflight Request)?

如果请求 不符合 简单请求的条件,浏览器会先发送一个 OPTIONS 预检请求,询问服务器是否允许跨域请求。

📌 什么时候触发预检请求?

如果请求满足以下任意条件,浏览器会 先发一个 OPTIONS 请求

  1. 请求方法不是 GETPOSTHEAD(如 PUTDELETEPATCH)。
  2. 请求头包含自定义字段(如 AuthorizationX-Requested-With)。
  3. Content-Type 不是 application/x-www-form-urlencodedmultipart/form-datatext/plain(如 application/json)。

🛠 预检请求示例

前端请求

javascript
fetch("https://api.example.com/update", {
  method: "PUT", // PUT 请求需要预检
  headers: {
    "Content-Type": "application/json", // 非允许的 Content-Type
    Authorization: "Bearer token", // 自定义 Header
  },
  body: JSON.stringify({ name: "Alice" }),
})
  .then((response) => response.json())
  .then((data) => console.log(data));

浏览器先发送预检请求(OPTIONS)

http
OPTIONS /update HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Authorization, Content-Type

服务器返回允许跨域

http
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: PUT, POST, GET
Access-Control-Allow-Headers: Authorization, Content-Type
Access-Control-Max-Age: 86400

然后浏览器才真正发送 PUT 请求

http
PUT /update HTTP/1.1
Origin: https://example.com
Authorization: Bearer token
Content-Type: application/json

服务器必须正确响应 Access-Control-Allow-* 头,否则浏览器会拦截请求。
Access-Control-Max-Age: 86400 表示 24 小时内不用再发送预检请求(提升性能)。


🎯 3. 预检请求 vs. 简单请求

对比项简单请求(Simple Request)预检请求(Preflight Request)
触发条件满足简单请求的 3 个条件请求方法不是 GET/POST/HEAD,或含自定义头
是否发送 OPTIONS 预检❌ 否✅ 是
请求头限制只能使用基本头部可以使用自定义头部
性能更快(少一次请求)需要先发送预检请求(性能稍差)
应用场景常见的 GETPOST 表单提交API 认证(Authorization)、PUT/DELETE 请求

🎉 总结

  1. 简单请求
    • 只有 GETPOSTHEAD 方法
    • 头信息受限(不能包含 AuthorizationCustom-Header 等)
    • Content-Type 只能是 application/x-www-form-urlencodedmultipart/form-datatext/plain
    • 不会触发预检请求
  2. 预检请求
    • 任何 不符合 简单请求条件的请求
    • 先发 OPTIONS 请求,询问服务器是否允许跨域
    • 服务器必须返回 Access-Control-Allow-* 头,否则请求被拦截

🚀 优化建议

  • 尽量使用简单请求 避免额外的预检请求,提高性能。
  • 增加 Access-Control-Max-Age,减少重复预检请求的开销。
  • 服务器配置 CORS 规则,正确返回 Access-Control-Allow-* 头。