Skip to content

Latest commit

 

History

History
357 lines (233 loc) · 17.2 KB

网络协议.md

File metadata and controls

357 lines (233 loc) · 17.2 KB

网络协议

常见的 HTTP Code

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

HTTP2 的优点

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

简述 TCP 连接的过程

假设 客户端(Client) 需要连接 服务器(Server),三次握手的过程如下:

  1. 第一次握手(客户端 → 服务器,SYN) 客户端 发送 SYN(同步)报文,表示请求建立连接,并携带 初始序列号(ISN,Initial Sequence Number)。

  2. 第二次握手(服务器 → 客户端,SYN + ACK) 服务器 收到 SYN 请求后,返回 SYN + ACK 报文,表示同意连接。同时,服务器也生成自己的初始序列号(ISN_S)。

  3. 第三次握手(客户端 → 服务器,ACK) 客户端 再次发送 ACK 报文,表示确认收到服务器的 SYN,连接正式建立!此时,连接已建立,双方可以进行数据传输。

中间人攻击

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

反向代理与正向代理

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

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

简述单点登录

单点登录(SSO,Single Sign-On)是一种 身份认证机制,允许用户在多个系统或应用之间只需登录一次,就能访问所有相关资源,而无需重复输入用户名和密码。

举个例子

  • 场景 1:用户登录 Google 账号 后,自动访问 Gmail、YouTube、Google Drive,无需重复登录。
  • 场景 2:用户在 企业门户 登录后,自动访问 CRM、OA、邮件系统等多个应用。

SSO 的核心原理

SSO 主要基于 统一身份认证,通过 共享 Token 或 Session 来实现跨系统登录。

基本流程如下:

  1. 用户访问业务系统 A(未登录)。
  2. 跳转到 SSO 认证中心(统一身份认证)。
  3. 用户输入账号密码,SSO 认证成功后,生成 Token/Session 并返回给业务系统 A。
  4. 业务系统 A 记录 Token,并允许访问。
  5. 用户访问业务系统 B,系统 B 检查 Token,如果有效,则直接放行(免登录)。

SSO 的实现方式

  • 基于 Cookie 共享
  • 基于 Token
  • 基于 SAML 协议
  • 基于 CAS

文件上传如何做断点续传

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

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

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

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

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

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

介绍 SSL 和 TLS

SSL(Secure Sockets Layer,安全套接字层):是一种加密通信协议,用于在客户端(浏览器)和服务器之间建立安全连接,保护数据不被窃取或篡改。

TLS(Transport Layer Security,传输层安全协议):是 SSL 的升级版,提供更安全的加密和身份验证机制。

现代浏览器和服务器基本上都使用 TLS,而不再使用 SSL。

SSL/TLS 主要通过 握手(Handshake) 过程来建立安全连接。

Client                       Server
   | ------ ClientHello ------> |   // 客户端发起连接
   | <----- ServerHello ------ |   // 服务器响应并发送证书
   | -- 发送对称加密密钥 --> |   // 客户端用公钥加密密钥
   | <--- 握手完成确认 ---> |   // 服务器解密并确认
   | ---- 安全通信开始 ----> |   // 开始加密传输

说说网络的五层模型

应用层 (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 允许的范围内。

🛠 简单请求示例

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/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)。

🛠 预检请求示例

前端请求

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)

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

服务器返回允许跨域

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 请求

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-* 头。

为什么使用分布式锁?

在分布式系统中,多个节点(服务器)可能会同时操作共享数据(如数据库、缓存、文件等) 为了防止数据竞争,数据不一致或超卖问题,需要分布式锁来确保同一时间只有一个节点能够访问某个关机资源

  • 比如用户更新个人资料,不用锁的话,会导致修改冲突,导致数据库状态不一致,导致线上事故
  • 电商平台的秒杀活动,如果多个服务器读取库存值,最后导致库存为负,产生数据库状态问题

网络安全

CSRF(Cross-Site Request Forgery,跨站请求伪造) 是一种利用用户身份在已登录的网站执行未授权操作的攻击。攻击者诱导用户访问恶意网站,从而在受害者不知情的情况下,以用户身份对目标网站执行操作(如转账、修改密码等)。

  • 攻击者借助用户的登录状态,在后台“冒充”用户发送恶意请求,导致用户账号被操作!

GraphQL

GraphQL 是 Facebook 在 2015 年开源的一种数据查询语言(Query Language),用于 API 端点查询和数据操作。它是一种替代 REST API 的方案,允许客户端精准获取所需的数据,而不会获取不必要的信息。

GraphQL 可以灵活订阅数据查询,不用获取无关的字段,避免多次重复请求,提供的强类型系统定义数据结构,提供类型约束和 API 文档功能,还允许客户端订阅时间变化

GraphQL 的局限性如下:

1. 查询复杂性和性能问题

  • REST API 通过固定的端点可以进行缓存,而 GraphQL 由于查询的灵活性,往往很难使用 HTTP 缓存,可能会增加服务器的查询负担。
  • 深层嵌套查询可能导致 N+1 查询问题(需要优化,比如使用 DataLoader)。

2. 学习成本较高

  • 需要掌握 Schema 设计、Resolver 实现、GraphQL 服务器配置等内容,初期比 REST API 更复杂。

3. 权限管理较复杂

  • REST API 可以基于端点进行权限控制,而 GraphQL 需要对每个字段进行更细粒度的权限管理,可能会增加开发难度。

4. 文件上传支持较弱

  • GraphQL 设计上是基于 JSON 传输的,不支持原生的文件上传,需要额外的 multipart 请求处理。

5. 社区成熟度和工具支持

  • REST API 生态非常成熟,而 GraphQL 仍在发展,部分后端框架可能需要额外配置才能良好支持。

https 的加密方式

HTTPS 结合 对称加密 和 非对称加密,

http 缓存

HTTP 缓存机制用于减少不必要的网络请求,提高页面加载速度,分为 强制缓存(强缓存) 和 协商缓存。

  • 强缓存(强制缓存) 浏览器本地缓存资源,避免发送 HTTP 请求。适用于 短时间内不会更新的资源(如图片、CSS、JS)。 cache-control

  • 协商缓存 当强缓存失效 时,浏览器向服务器发送请求,并通过 协商缓存 判断是否需要重新下载资源。 Last-Modified & If-Modified-Since/eTag/if-none-match