跳到主要内容

15 篇博文 含有标签「网络与协议」

网络技术和协议相关文章

查看所有标签

HttpOnly 的用处

· 阅读需 2 分钟
素明诚
Full stack development

HttpOnly 是一个设置在 cookies 上的属性,用于阻止客户端 JavaScript 访问这些 cookies,以提高网站安全性,特别是防止跨站脚本(XSS)攻击

背景和详细说明

背景 HttpOnly 最初由 Microsoft 引入,并在 2002 年首次出现在 Internet Explorer 中,目的是增强 Web 应用的安全性

原因 出现是为了减少 XSS 攻击的风险,这类攻击可能会劫持用户会话或窃取敏感信息,如认证 tokens

功能 HttpOnly 属性用于限制 cookies 仅可通过 HTTP(S) 请求访问,使得客户端脚本(如 JavaScript)无法读取或修改这些 cookies

设置方法 在设置 cookie 时,将 HttpOnly 标志加入响应头中 例如在 Go 语言的 HTTP 服务器代码中,你可以这样设置:

    router.GET("/set-cookie", func(c *gin.Context) {
// 设置一个 HttpOnly 的 Cookie
http.SetCookie(c.Writer, &http.Cookie{
Name: "session_token",
Value: "some_secure_token",
Expires: time.Now().Add(24 * time.Hour), // 设置过期时间
HttpOnly: true, // 确保 HttpOnly 标志被设置
})

c.String(http.StatusOK, "Cookie set successfully")
})

设置后的好处

安全性增强 设置 HttpOnly 后,即使网站出现 XSS 漏洞,也难以通过客户端脚本直接获取标记为 HttpOnly 的 cookies,有效降低信息泄露风险

数据保护 保护用户数据不被恶意脚本窃取,尤其是在涉及身份验证和用户会话管理时

TCP 三次握手的工作流程

· 阅读需 4 分钟
素明诚
Full stack development

工作流程

SYN:客户端发送一个 SYN(同步序列编号)包到服务器,并进入 SYN_SEND 状态,等待服务器确认。

SYN-ACK:服务器接收到 SYN 包,必须确认客户的 SYN(ACK)并同时自己也发送一个 SYN 包,即 SYN+ACK 包,此时服务器进入 SYN_RECV 状态。

ACK:客户端收到服务器的 SYN+ACK 包后,向服务器发送确认包 ACK,此包发送完毕,客户端和服务器进入 ESTABLISHED 状态,完成三次握手。

详解

同步序列编号(SYN)

同步序列编号(SYN)是在 TCP 协议中用来标识数据包序列的数字,它是三次握手过程的一部分。在 TCP 连接的初始化阶段,SYN 标志被设置为 1,以表明一个连接请求或连接接受。序列编号是随机产生的,用于标记传输的数据包的顺序,确保数据的有序和完整性。

术语描述
SYN标志位,用于启动一个新连接,同时携带一个随机的序列号作为开始。

ESTABLISHED 状态

ESTABLISHED 状态表示 TCP 连接已经成功建立,两端的设备可以开始数据传输。在三次握手过程中,当双方交换完所有必要的确认消息后,连接状态就会变为 ESTABLISHED。这个状态是双向的,即数据可以从任一端向另一端发送。

打电话类似三次握手

  1. 拨打电话:当你拨打电话给某人时,你的电话会向对方的电话发送一个信号,请求建立连接(相当于发送 SYN)。
  2. 响铃并接听:对方的电话响铃,当他们接听时,他们的电话会发送一个信号回到你的电话,表明他们已准备好接受通话(相当于发送 SYN-ACK)。
  3. 开始通话:你听到对方接听的声音或信号后,通话开始(相当于发送 ACK),此时双方都知道连接已建立,可以开始通话了。

为什么是三次?两次不行吗?

在两次握手的情况下

  • 客户端发送一个带有 SYN 的数据包到服务器,请求建立连接。
  • 服务器返回一个带有 SYN 和 ACK 的数据包,表示接受连接请求。

这里的问题是,虽然服务器知道客户端能够接收数据(因为客户端收到了服务器的响应),但服务器没有确切的方式来确认客户端是否还在继续能够发送数据。如果在服务器响应之后,客户端发生故障或连接中断,服务器可能会在不知情的情况下保持一个无效的连接,这会浪费服务器资源。

防止旧连接请求的执行

三次握手的设计还可以防止已经失效的连接请求被错误地建立为新的连接。考虑这样一个场景

  • 客户端之前发送了一个连接请求(SYN),但因为某种原因(如网络延迟),这个请求在很长时间后才到达服务器。
  • 在两次握手的协议中,服务器会立即接受这个迟到的连接请求并发送确认(SYN-ACK),然后认为连接已建立。

在这种情况下,如果没有第三次握手(客户端的 ACK),服务器无法确定客户端是否真的还想建立连接或者是否已经接收到了它的 SYN-ACK 响应。这样可能导致服务器开启一些根本不需要的连接。

所以如果是两次握手存在导致资源浪费的风险

TCP 与 UDP 区别和场景

· 阅读需 5 分钟
素明诚
Full stack development

TCP(Transmission Control Protocol,传输控制协议)

特点

  • 可靠性:TCP 提供可靠的数据传输服务,通过序列号、确认应答、重传机制等确保数据完整性和正确性。
  • 有序性:TCP 保证数据包的顺序,数据将按照发送顺序到达接收端。
  • 流控制:TCP 使用窗口机制进行流控制,根据接收方的接收能力调整发送速率,避免发送方过快发送数据使接收方来不及处理。
  • 拥塞控制:TCP 具有拥塞控制机制,能够根据网络条件调整数据发送速率,减少网络拥塞。

适用场景

  • Web 页面加载:确保网页数据完整无误地传输。
  • 文件传输:如 FTP(文件传输协议)需要可靠地传输大文件。
  • 电子邮件传输:如 SMTP(简单邮件传输协议)要求邮件数据准确无误地送达。
  • 远程服务器访问:如 SSH(安全外壳协议)和 Telnet 依赖于 TCP 的可靠连接。

TCP 滑动窗口

TCP 滑动窗口是一种流量控制机制,用于控制发送方在等待接收方确认之前可以发送的数据量。这个窗口的大小决定了可以发送的未被确认的数据包的数量或大小,这有助于防止接收方被过量的数据淹没。

  • 窗口大小:接收方根据其当前的处理能力和缓冲区的大小来告诉发送方窗口的大小,即发送方在接收方发回确认之前可以发送的数据的最大量。
  • 动态调整:窗口大小会根据网络条件动态调整。如果网络状况良好,窗口会增大,允许发送更多的数据;如果网络状况不佳,窗口会减小,限制数据流量,避免数据丢失。

拥塞控制

拥塞控制是一种网络控制机制,用来防止过多的数据包在网络中同时传输,从而导致网络拥堵。TCP 通过几种算法来实施拥塞控制,这些算法包括慢启动、拥塞避免、快重传和快恢复。

  • 慢启动(Slow Start):连接开始时,拥塞窗口(cwnd)从一个很小的值开始,例如 1 个数据包,随着每次传输轮次的成功完成,窗口大小指数级增长,直到达到一个阈值(ssthresh)。
  • 拥塞避免(Congestion Avoidance):一旦窗口大小达到或超过阈值,增长策略会转变为线性增长,即每个传输轮次只增加一个数据包的大小,以减少引起拥塞的风险。
  • 快重传和快恢复(Fast Retransmit and Fast Recovery):当发送方收到三个重复确认(表示一个数据包可能已丢失),它会立即重传丢失的数据包,而不是等待重传计时器超时。此时,拥塞窗口和阈值会调整以快速恢复传输。

UDP(User Datagram Protocol,用户数据报协议)

特点

  • 无连接:UDP 是无连接的,发送数据之前不需要建立连接,减少了开销和延迟。
  • 高效:UDP 头部开销小,仅有 8 字节,相较于 TCP 的 20 字节更为高效。
  • 不保证可靠性:UDP 不保证数据包的顺序、完整性或者可靠性,不进行错误校正。
  • 无拥塞控制:UDP 不进行拥塞控制,即使网络条件不佳,仍然会以相同的速率发送数据。

适用场景

  • 实时应用:如语音通信、在线游戏和实时视频会议、直播,这些应用需要快速传输,可以容忍一定程度的数据丢失。
  • 广播和多播应用:UDP 支持发送单个数据包到多个接收者(广播)或者选定的多个接收组(多播)。
  • DNS 查询:域名系统(DNS)查询使用 UDP 进行快速查找,通常不需要可靠传输。

FAQ:BT 和 P2P 用的是什么协议?

BT 下载(BitTorrent)和 P2P(Peer-to-Peer)下载通常使用 TCP 协议,这与它们对数据完整性的高要求有关。这些下载方式涉及将大文件分割成多个小片段,并从不同的对等方(peers)下载这些片段,最终在本地组合成完整的文件。以下是对这些协议选择的详细说明

  • TCP 的可靠性:由于 BT 和 P2P 下载的文件往往较大,且来自多个不同的数据源,确保每一个数据片段的完整性和正确顺序对于最终文件的完整性至关重要。TCP 协议通过其内置的错误检查和纠正机制(如数据重传、数据包排序等),保证了数据的可靠传输。
  • 数据完整性:在 BT 或 P2P 下载中,每个文件片段的完整和准确至关重要,因为最终的文件需要所有片段完整无误才能正确组装和使用。TCP 保证每个数据包都将按顺序并完整地到达,如果发生丢包,TCP 将会重新发送丢失的数据包。
  • 拥塞控制:TCP 还具备拥塞控制机制,可以根据网络条件调整数据传输速率,这在多对等方环境中尤其重要,因为网络状况可能因参与者的不同而大相径庭。这有助于优化整体网络性能并避免网络拥塞。

虽然 TCP 是 BT 和 P2P 协议中常用的传输协议,但这并不排除在某些特定场景下使用 UDP。例如,一些 P2P 实时视频流或实时数据广播可能会选择 UDP,以减少延迟。但对于文件下载这类对数据完整性要求极高的应用,TCP 是更常见的选择

TCP 四次挥手过程

· 阅读需 3 分钟
素明诚
Full stack development

四次挥手的步骤

第一次挥手:客户端发送 FIN

  • 动作:客户端决定结束发送数据,向服务器发送一个带有 FIN 标志的数据包。
  • 状态变迁:客户端发送 FIN 后,进入 FIN-WAIT-1 状态,等待服务器的确认(ACK)。

第二次挥手:服务器发送 ACK

  • 动作:服务器收到客户端的 FIN 后,返回一个 ACK 数据包,确认序号为收到的序号加 1。
  • 状态变迁:客户端接收到 ACK 后,进入 FIN-WAIT-2 状态。服务器进入 CLOSE-WAIT 状态,准备结束自己的发送。

第三次挥手:服务器发送 FIN

  • 动作:服务器完成其数据的发送后,向客户端发送一个带有 FIN 标志的数据包,请求关闭连接。
  • 状态变迁:服务器发送完 FIN 后,等待客户端的最终 ACK 确认,进入 LAST-ACK 状态。

第四次挥手:客户端发送 ACK

  • 动作:客户端收到服务器的 FIN 后,返回一个 ACK 数据包,确认序号为收到的序号加 1。
  • 状态变迁:客户端发送 ACK 后,进入 TIME-WAIT 状态,保持该状态足够的时间以确保服务器接收到 ACK。该时间通常是最大报文段生存时间(Maximum Segment Lifetime, MSL)的两倍。完成这个等待后,客户端最终转入 CLOSED 状态。
方向描述客户端状态服务器状态
客户端 -> 服务器客户端发送 FIN,请求关闭连接FIN_WAIT_1-
服务器 -> 客户端服务器确认,发送 ACK 响应FIN_WAIT_2CLOSE_WAIT
服务器 -> 客户端服务器发送 FIN,请求关闭连接-LAST_ACK
客户端 -> 服务器客户端发送 ACK,确认收到关闭请求TIME_WAITCLOSED

为什么挥手需要四次?

为了保证数据完整传输

CLOSE-WAIT

等待关闭

TIME-WAIT

为了解决网络的丢包和网络不稳定所带来的其他问题,确保连接方能在时间范围内,关闭自己的连接

如何查看 TIME-WAIT 状态的链接数量?

netstat -an |grep TIMEWAIT|wc -l 查看连接数等待timewait状态连接数

为什么会 TIME-WAIT 过多?解决方法是怎样的?

  • 高频短连接:如果应用频繁地建立并快速关闭连接,那么在任意时刻都可能有大量的连接处于 TIME-WAIT 状态。这种情况在使用不当的客户端-服务器通信模型中很常见,如每个请求都建立新连接的 HTTP/1.0。而 HTTP/1.1 默认支持 HTTP Keep-Alive
  • 资源消耗:每个处于 TIME-WAIT 的连接都会占用服务器资源(如端口和内存),过多的 TIME-WAIT 连接可能耗尽这些资源,导致性能下降或无法建立新的连接。

简单请求和复杂请求

· 阅读需 2 分钟
素明诚
Full stack development

简单请求

使用以下方法之一

  • GET
  • POST
  • HEAD

设置的头信息仅限于以下几种

  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type(但仅限于application/x-www-form-urlencodedmultipart/form-datatext/plain
  • 请求中的任何XMLHttpRequestUpload对象没有注册任何事件监听器;XMLHttpRequestUpload对象可以使用XMLHttpRequest.upload属性访问。
  • 请求中没有使用ReadableStream对象。

满足上述条件的请求被视为“简单请求”。简单请求不会触发 CORS 预检请求(这里指的是浏览器)。

复杂请求

不符合上述简单请求条件的请求被视为复杂请求。复杂请求在正式通信之前,会先发送一个预检请求(preflight request),这是一个使用OPTIONS方法的HTTP请求,向服务器询问实际请求是否安全可接受。

复杂请求的特点包括

  • 使用了除 GET、POST、HEAD 之外的 HTTP 方法(如 PUT、DELETE 等)。
  • 人为设置的头信息超出了简单请求允许的范围。
  • 向服务器发送了除允许的类型之外的Content-Type,如application/json

预检请求的目的是为了确保服务器明确允许跨源请求。服务器必须正确响应预检请求,提供相应的Access-Control-Allow-MethodsAccess-Control-Allow-Headers等 CORS 相关的响应头,表明服务器接受实际请求。只有当预检请求成功后,浏览器才会发送实际的请求。

简单请求和复杂请求的区别主要是为了安全考虑,通过这种机制,可以避免恶意网站对跨源资源进行未经授权的访问。其实我们可以发现,除了 GET、POST、HEAD 之外,其他类型的请求都涉及到修改数据库的内容,所以为了安全,需要进行预检。只要触发了预请求就是复杂请求

如果您喜欢这篇文章,不妨给它点个赞并收藏,感谢您的支持!

GET 请求查询字符串和路径参数的区别

· 阅读需 2 分钟
素明诚
Full stack development

查询字符串(Query String)

GET /resource?id=2

  • 这是传统的方法,将参数添加到 URL 的查询字符串中。
  • 它适用于过滤结果或传递非层级性的数据。
  • 它使得参数可选,可以很容易地添加更多的参数,例如 GET /resource?id=2&sort=asc&category=books
  • 此方法在 URL 的长度和结构上可能有限制,因为有些浏览器和服务器对 URL 长度有限制。

路径参数(Path Parameter)或 RESTful 参数

GET /resource/2

  • 这种方法通常用于 RESTful API,参数是 URL 路径的一部分,前端更喜欢这种。
  • 它适用于指定资源或资源的特定操作,表达了一种层级关系。
  • URL 看起来更加清洁和“友好”,这有时候被称为“clean URLs”或“pretty URLs”。
  • 在设计 RESTful API 时,路径参数常用来获取特定资源或资源集合。

建议使用哪一种?

  • 如果你在设计一个RESTful API,通常会使用路径参数来获取特定资源。例如,GET /users/2 来获取 ID 为 2 的用户。
  • 如果你需要过滤列表或者有很多可选的参数,那么查询字符串可能更合适。例如,GET /users?id=2 可以用来从用户集合中过滤出 ID 为 2 的用户,同时还能添加其他过滤选项,如 GET /users?role=admin

跨域到底跨了什么域

· 阅读需 2 分钟
素明诚
Full stack development

在网络编程和 Web 开发的背景下,"域"(Domain)通常指的是互联网上的一个命名区域,这通常对应于一个域名(如 sumingcheng.com)。但在涉及跨域(Cross-Origin)问题时,"域"或"源"(Origin)的概念更加具体,它不仅包括域名,还包括协议(如 HTTP 或 HTTPS)和端口号。这三部分共同构成了一个完整的"源"。

所以,跨域这个词我们不妨理解成跨源,那么源就好解释了。

同源策略

当涉及到同源策略时,只有当这三个部分(协议、域名、端口号)完全一致时,两个 URL 才被认为是来自同一个"源"。如果任何一部分不同,那么它们就属于不同的"源"。

为什么要有同源策略?

核心是为了保证服务器的安全,例如

跨站脚本攻击(XSS)

  • 如果浏览器允许脚本自由地访问跨源数据,恶意网站就可以通过注入脚本来窃取其他网站的敏感信息(如 cookies、session tokens 等)。这种攻击通常在用户不知情的情况下发生,可能导致隐私泄露和安全风险。

跨站点请求伪造(CSRF)

  • 如果跨源请求没有适当的限制和验证,攻击者可以伪造用户的请求,例如在用户登录银行网站时,恶意网站可能在后台发起转账请求。这种攻击利用了用户的登录状态和网站对用户身份的信任。

保护用户数据

  • 同源策略阻止了一个源的网页访问另一个源的敏感数据,包括存储在浏览器中的数据,如 LocalStorage、IndexedDB 和 Web SQL 数据库。

隔离潜在恶意内容

  • 限制脚本跨源通信有助于隔离和限制潜在的恶意内容,提高网站和用户的整体安全性。

什么是 RESTful API

· 阅读需 2 分钟
素明诚
Full stack development

RESTful API(Representational State Transfer API)既是一种技术模式,也是一种设计标准或风格。它并不是一个正式的标准,而是一系列架构原则和约束条件的集合。

这些原则和约束条件旨在利用现有的 Web 技术和协议(如 HTTP),以一种简单、高效、可扩展、可靠和可移植的方式来设计和开发分布式系统。RESTful API 强调资源的表现层和客户端-服务器之间的无状态通信,目的是提高网络应用的性能、可伸缩性和简化修改。它已成为开发 Web 服务的流行方法。

实际使用

比如我们某个请求的接口,可能是以下这几种形式

# 获取 notes
GET /notes
# 获取 notes id 的数据
GET /notes/id

这种接口,我们是不用考虑服务端内部是怎么实现的,只需要知道这是彼此交互的接口

客户端不知道服务器到底有多少个中间层,也不需要知道

某些请求,比如 get /notes 可以在客户端或者服务端缓存一段时间

遵循以上的这些原则,就是 RESTful API

RESTful API 中文叫什么?

RESTful API 翻译成中文通常被称作“表现层状态转移应用编程接口”。这里,“表现层”指的是资源的表现层,即资源的具体表示形式(如 JSON、XML 等);“状态转移”则是指通过 HTTP 动词(如 GET、POST、PUT、DELETE 等)来表达对资源的操作,实现应用的状态转换。这种设计风格强调资源的识别、通过标准的 HTTP 方法进行操作,以及无状态通信,是构建 Web 服务的一种流行方法。

HTTP请求参数类型及其在Swagger文档和实际请求中的表示方式

· 阅读需 1 分钟
素明诚
Full stack development
参数类型Swagger 描述说明示例(传参形式)
Query Parameters参数在 URL 的查询部分使用 ? 开始,并使用 & 分隔多个参数http://sumingcheng.cn/api?param=value
Path Parameters参数是 URL 路径的一部分路径参数通常用花括号 表示,并在实际请求中替换为实际值http://sumingcheng.cn/api/users/{userId}
Request Body参数在 HTTP 请求体中通常用于 POST、PUT 或 PATCH 请求,可以是 JSON、XML 等格式{ "username": "John", "email": "john@sumingcheng.cn" }
Header Parameters参数在 HTTP 请求头中用于传递额外的元数据,如身份验证令牌、客户端可接受的内容类型等Authorization: Bearer token_value
Cookie Parameters参数在 HTTP cookies 中用于会话管理、用户跟踪等sessionId=12345
Form Data Parameters参数在表单数据中通常用于提交 HTML 表单,使用 application/x-www-form-urlencoded 或 multipart/form-data 格式username=John&email=john@sumingcheng.cn

比较 TCPHTTP 和 WebSocket 三种协议

· 阅读需 1 分钟
素明诚
Full stack development
特性 / 协议TCPHTTPWebSocket
是否基于连接是,是一种面向连接的协议是,但默认每次请求都需要重新建立连接(HTTP/1.1 引入了 keep-alive 机制以复用连接)是,一次握手后建立持久连接
可靠性是,通过 ACK、序列号、重传机制等保证是,因为基于 TCP是,因为基于 TCP
通信方式全双工半双工,客户端发送请求后等待并接收响应全双工
数据流向双向单向,从客户端发送请求到服务端响应双向,可以从客户端到服务端,也可以从服务端到客户端
头部信息无,仅在握手时有少量开销每次请求和响应都有头部信息,可能导致额外开销握手时有开销,但之后数据传输的头部开销非常小
使用场景低级别的网络通信,不特定于应用场景网页请求,API 请求,短连接实时或需要服务器主动推送的应用,如聊天应用、在线游戏等