网络分层的理解
网络通信是一个很复杂的问题所以把它拆成多层每一层只负责解决一类问题。上层不用关心下层具体怎么实现只需要使用下层提供的服务。首先要有整个网络分层的认知┌─────────────────────────────┐ │ 应用层 Application │ │ HTTP / HTTPS / DNS / WebSocket│ │ │ │ 解决我要传什么 │ └──────────────▲──────────────┘ │ ┌──────────────┴──────────────┐ │ 传输层 Transport │ │ TCP / UDP / QUIC │ │ │ │ 解决怎么可靠/高效地传给 │ │ 对方的哪个进程 │ └──────────────▲──────────────┘ │ ┌──────────────┴──────────────┐ │ 网络层 Network │ │ IP / ICMP │ │ │ │ 解决数据包怎么找到目标机器 │ └──────────────▲──────────────┘ │ ┌──────────────┴──────────────┐ │ 链路层 Link │ │ Ethernet / Wi-Fi │ │ │ │ 解决数据怎么在当前网络中 │ │ 从一个设备传到另一个 │ └─────────────────────────────┘为什么一定要分层假设写了一个Java Web服务GetMapping(/user/1)publicUsergetUser(){...}写的是HTTP但是HTTP自己根本没有能力找到服务器IP把数据从电脑传到服务器保证数据不丢判断数据属于哪个Java进程通过网线WiFI发送比特上面的问题当成面试官来问你自己能不能回答上来。所以HTTP必须依赖下面的东西HTTP ↓ TCP ↓ IP ↓ Ethernet / Wi-Fi ↓ 网卡 ↓ 交换机 / 路由器 / Internet ↓ 服务器应用层应用层解决的是应用程序之间到底要交换什么信息以及信息按照什么格式表达。典型的就是HTTP, DNS, WebSocket, SMTP, FTP例如浏览器访问“https://www.example.com/user/123”HTTP可以表达为GET /user/123 HTTP/1.1 Host: www.example.com Authorization: Bearer xxx这里解决的就是“我要想服务器请求/user/123”服务器返回HTTP/1.1 200 OK Content-Type: application/json { id: 123, name: Tom }HTTP规定了请求方法、URL、Header、Body、Status Code、ContentType、Cookie、Cache-Control扩展Cookie, Session, Token, JWT, 浏览器存储HTTP请求鉴权Cookie是HTTP协议中的一种客户端状态携带机制Token是一种身份凭证浏览器的LocalStorage, SessionStorage是存储位置**Cookie**本质上是一小段服务器要求浏览器保存并在后续符合条件的HTTP请求中自动携带的数据例如用户第一次登录浏览器 │ │ POST /login │ usernameTompassword123 ↓ 服务器 │ │ 登录成功 │ │ Set-Cookie: sessionIdabc123 ↓ 浏览器服务器的响应式HTTP/1.1 200 OK Set-Cookie: sessionIdabc123; HttpOnly; Secure浏览器看到Set-Cookie之后就会把sessionIdabc123保存起来以后访问接口GET /users/profile浏览器就会自动带Cookie: sessionIdabc123所以Cookie是通过HTTP Header在客户端和服务器之间传递的。LocalStorage实际上Cookie, LocalStorage, SessionStorage都是浏览器存储数据的机制但行为不同。Cookie浏览器保存访问符合Domain/Path等条件的服务器时会自动带上LocalStorage浏览器保存token但是浏览器不会自动把LocalStorage里的token放到HTTP请求里必须JavaScript主动拿出来发送给服务器另外注意Cookie有带来了CSRF问题跨站请求伪造。所以Cookie鉴权经常需要SameSite, CSRF Token, Origin/ Referer校验。鉴权Session鉴权JWT最传统的Cookie Session。结合下面流程图理解登录 浏览器 ───── username/password ─────→ 服务端 │ ↓ 创建 Session │ ↓ sessionIdabc123 │ 浏览器 ←──── Set-Cookie ──────────────┘ 后续请求 浏览器 ── Cookie: sessionIdabc123 ──→ 服务端 │ ↓ Redis查询 │ ↓ userId10001 │ ↓ 鉴权成功这里cookie存的sessionId实际就是一个索引/凭证所以Session鉴权属于有状态鉴权服务器保存用户登录状态。JWT是另一种思路希望把一部分用户信息直接放进token中由客户端携带浏览器 ↓ 用户名 密码 ↓ 服务器 ↓ 验证成功 ↓ 生成 JWT ↓ 返回 Token浏览器保存tokoen然后下次请求请求中带上Authorization: Bearer token拿到 JWT ↓ 验证签名 ↓ 验证 exp ↓ 读取 userId ↓ 鉴权成功这里不一定需要Redistoken -UserId因此JWT常被用于无状态鉴权。理解无状态JWT把用户身份信息直接编码进了令牌本身服务端拿到令牌就能自己验证并读出UserId不需要再去redis里查一次映射关系。而JWT方案是userId直接写在token里JWT, JSON Web Token三段式结构Header.Payload.Signature其中Payload是一段Json经过Base64Url编码里面可以直接放用户消息{sub:10086,name:张三,exp:1735689600}服务端签发时用密钥对Header.Payload做签名得到Signature最终token客户端下次请求带上它服务端拿到后用密钥重新计算签名和 token 里的 Signature 比对验证没被篡改。验证通过后直接 Base64 解码 Payload读出 sub 字段也就是 UserId 10086。检查 exp 是否过期。全程不需要查 Redis因为 UserId 就在 token 里签名保证了它不可伪造。这正是JWT适合分布式、微服务、Serveless场景的原因多个服务实例不需要共享redis就能独立鉴权。另外注意JWT是token的一种格式LocalStorage是浏览器保存数据的地方所以有这样的认知鉴权凭证 │ ┌────────────┴────────────┐ ↓ ↓ Session JWT │ │ │ │ sessionId Token │ ↓ Cookie鉴权凭证的两种方式然后存储是Cookie或者LocalStorage整理的术语概念它是什么主要作用HTTP应用层协议定义请求/响应CookieHTTP 状态机制浏览器自动携带数据LocalStorage浏览器存储保存前端数据Session服务端会话状态保存用户登录状态SessionId会话标识找到服务端 SessionToken身份凭证证明用户身份JWTToken 的一种格式自包含身份信息 签名Access Token访问凭证调用 APIRefresh Token刷新凭证获取新的 Access TokenAuthentication认证证明“你是谁”Authorization授权判断“你能干什么”RBAC授权模型用户→角色→权限HttpOnlyCookie 属性限制 JS 读取SecureCookie 属性限制 HTTPS 传输SameSiteCookie 属性控制跨站携带传输层传输层解决的就是端到端的进程通信IP解决的是哪台机器TCP解决的事这台机器上的哪个应用进程。例如192.168.1.10:8080这就是为什么Java Web服务监听8080IP ↓ 找到机器 TCP Port ↓ 找到机器上的进程HTTP给TCP的数据 TCP会通过可靠传输机制传输过去而不是简单的将给的数据直接扔到网络上这里可靠传输机制就不细讲了之前已经理解过。网络层网络层负责把数据包从一个网络中的主机送到另一个网络中的主机。这里面试官可能问我浏览器是访问www.baidu.com怎么送到百度服务器IP层负责根据IP地址进行路由。IP负责主机到主机的寻址和路由TCP负责端到端的可靠传输以及进程间通信。例如192.168.1.10:54321 ↓ TCP ↓ 8.8.8.8:443IP跨网络找到对应机器然后TCP找到对应进程或服务进行连接传输链路层现在IP, TCP都对好了这一跳到底怎么传。典型技术Ethernet, Wi-FiIP是逻辑地址MAC是链路层地址/网卡地址。当在当前局域网中真正发送数据时需要知道当前下一跳设备的网卡地址。例如电脑 192.168.1.10 ↓ 想访问 192.168.1.20知道IP还需要知道1.20对应了哪个MAC会涉及到ARP实现IP和MAC的映射查询真正发送一个HTTP请求时以TCP/IP四层模型应用层浏览器请求得到HTTP Data传输层使用TCPTCP添加自己的Header┌──────────────┐ │ TCP Header │ ├──────────────┤ │ HTTP Data │ └──────────────┘里面包含了源端口、目标端口、序列号、确认号、窗口…形成TCP SegmentIP层TCP Segment交给IP┌──────────────┐ │ IP Header │ ├──────────────┤ │ TCP Header │ ├──────────────┤ │ HTTP Data │ └──────────────┘IP Header中有源IP, 目标IPTTL, 协议类型…形成IP Packet链路层中IP Packet再交给Ethernet / Wifi┌────────────────┐ │ Ethernet Header│ ├────────────────┤ │ IP Header │ ├────────────────┤ │ TCP Header │ ├────────────────┤ │ HTTP Data │ └────────────────┘这时候才变成当前链路可以发送的数据帧Ethernet Frame然后经过网卡 -》 网线/Wifi -》交换机/路由器 -》Internet上述的过程就是封装Encapsulation到了服务器Ethernet ↓ 去掉 Ethernet Header ↓ IP ↓ 去掉 IP Header ↓ TCP ↓ 去掉 TCP Header ↓ HTTP ↓ 交给 Web Server就是解封装Decapsulation