构建一个聊天室需要的基础知识 更新中 

基础知识 TCP 三次握手 客户端 - 服务器 三次握手目的:客户端的收发没问题,服务器的收发也没问题。 第一次握手:客户端发 SYN(同步请求) 客户端:我啥也不知道,我发个 SYN 消息出去,看看有没有人接收到。 如果没人回复,我再发几次(超时重传)。 这个时刻,客户端知道的事实是: 我发出去了,但不知道有没有人收到 ❌ 我能不能收消息?不知道 ❌ 对方存不存在?不知道 ❌ 第二次握手:服务器回 SYN+ACK(同步+确认) 服务器收到了客户端的 SYN。 服务器回复 SYN+ACK:“我收到你的消息了,我也发一条试试,看看你能不能收到。” 这个时刻,服务器知道的事实是: 客户端发消息是没有问题的 ✅(因为我收到了) 服务器收消息是没有问题的 ✅(因为我收到了) 服务器不知道服务器发消息有没有问题 ❌(我发出去了,但不知道对方收到没) 服务器不知道客户端收消息有没有问题 ❌(我发出去了,但不知道对方收到没) 服务器需要发送一条 SYN+ACK,等对方回复 ACK 来确认“我能发、对方能收” 当客户端收到 SYN+ACK 后,客户端可以确定以下事实: 我发消息是没有问题的 ✅(我发的 SYN 被收到了) 我收消息也是没有问题的 ✅(我收到了对方的回复) 服务器收消息是没有问题的 ✅(对方收到了我的 SYN) 服务器发消息也是没有问题的 ✅(我收到了对方的 SYN+ACK) ✅ 客户端这边已经确认全双工通信没问题了! 但是服务器他还有顾虑(不知道自己能不能发、不知道我能不能收),我再发个 ACK 给他吧 第三次握手:客户端发 ACK(确认) 客户端收到 SYN+ACK 后,回复一个 ACK:“我收到你的 SYN+ACK 了,我这边收发都没问题,你也可以放心了。” 当服务器收到这个 ACK 后,服务器可以确定以下事实: ...

2026-04-03 11:45:26 AM · 9 分钟

为什么有时候后端需要维护一张Refresh_Tokens表

正常 JWT 请求流程 sequenceDiagram participant User as 用户 participant Frontend as 前端(浏览器/App) participant Auth as 认证服务器 participant Backend as 后端API服务器 Note over User,Backend: 1. 登录阶段 User->>Frontend: 输入用户名/密码 Frontend->>Auth: POST /login (凭证) Auth->>Auth: 验证凭证 Auth-->>Frontend: 返回 access_token + refresh_token Frontend->>Frontend: 存储token(内存/localStorage) Frontend-->>User: 登录成功 Note over User,Backend: 2. 正常请求阶段 User->>Frontend: 请求受保护资源 Frontend->>Backend: GET /api/resourceAuthorization: Bearer access_token Backend->>Backend: 验证access_token签名和过期时间 Backend-->>Frontend: 返回请求的资源 Frontend-->>User: 展示数据 Note over User,Backend: 3. Access Token过期 User->>Frontend: 继续请求 Frontend->>Backend: GET /api/resourceAuthorization: Bearer access_token(已过期) Backend-->>Frontend: 401 Unauthorized (token过期) Frontend->>Frontend: 检测到401,触发刷新逻辑 Note over Frontend,Auth: 4. 刷新Token阶段 Frontend->>Auth: POST /refreshrefresh_token Auth->>Auth: 验证refresh_token Auth-->>Frontend: 返回新的 access_token(可选的新refresh_token) Frontend->>Frontend: 更新存储的access_token Frontend->>Backend: 重试原请求(新access_token) Backend-->>Frontend: 返回请求的资源 Frontend-->>User: 展示数据 为什么不能只靠JWT refresh token 发出去后后端不保存,会变成 不可控的长期通行证 无法主动踢人下线 无法注销单点设备 无法判断 token 是否被盗用(攻击者拿到了 refresh token 可以一直刷新 access token) 无法实现会话管理 使用 refresh tokens 表后的流程图 sequenceDiagram participant User as 用户 participant Frontend as 前端 participant Auth as 认证服务器 participant DB as 数据库(refresh_tokens表) participant Backend as 后端API服务器 Note over User,DB: 1. 登录阶段(签发token + 入库) User->>Frontend: 输入用户名/密码 Frontend->>Auth: POST /login Auth->>Auth: 验证凭证 Auth->>DB: 生成唯一refresh_token_idINSERT INTO refresh_tokens(user_id, token_hash, expires_at, device_info, ip_address, revoked) DB-->>Auth: 插入成功 Auth->>Auth: 生成access_token + refresh_token(refresh_token包含id引用) Auth-->>Frontend: 返回access_token + refresh_token Frontend->>Frontend: 存储token Frontend-->>User: 登录成功 Note over User,Backend: 2. 正常请求(与之前相同) User->>Frontend: 请求资源 Frontend->>Backend: GET /api/resourceAuthorization: Bearer access_token Backend->>Backend: 验证access_token Backend-->>Frontend: 返回资源 Note over Frontend,DB: 3. Access Token过期 → 刷新 Frontend->>Backend: GET /api/resource (access_token过期) Backend-->>Frontend: 401 Unauthorized Frontend->>Auth: POST /refreshrefresh_token Note over Auth,DB: 4. 刷新验证(多步校验) Auth->>Auth: 解析refresh_token,提取token_id Auth->>DB: SELECT * FROM refresh_tokensWHERE id = token_id DB-->>Auth: 返回记录 Auth->>Auth: 校验清单: Note over Auth: ✅ token_hash是否匹配✅ 是否过期 (expires_at > now())✅ 是否被撤销 (revoked = false)✅ 用户是否仍有效✅ 设备信息是否一致(可选) alt 校验全部通过 Auth->>DB: UPDATE refresh_tokensSET last_used_at = now(), last_used_ip = current_ipWHERE id = token_id Auth->>Auth: 生成新access_token(可选:延长refresh_token有效期) Auth-->>Frontend: 返回新access_token Frontend->>Frontend: 更新access_token Frontend->>Backend: 重试原请求(新token) Backend-->>Frontend: 返回资源 else 校验失败 Auth-->>Frontend: 401/403 (刷新失败) Frontend->>Frontend: 清除所有token Frontend->>User: 跳转登录页 end Note over User,DB: 5. 主动登出 User->>Frontend: 点击登出 Frontend->>Auth: POST /logoutrefresh_token Auth->>DB: UPDATE refresh_tokensSET revoked = trueWHERE id = token_id Auth-->>Frontend: 登出成功 Frontend->>Frontend: 清除本地token Frontend-->>User: 已登出 Note over User,DB: 6. 安全场景:密码修改 User->>Frontend: 修改密码 Frontend->>Auth: POST /change-password Auth->>DB: UPDATE refresh_tokensSET revoked = trueWHERE user_id = current_user_id Note over DB: 撤销该用户所有refresh_token(强制所有设备重新登录) Auth-->>Frontend: 密码修改成功 Frontend->>Frontend: 清除本地token Frontend-->>User: 请重新登录

2026-03-02 08:07:07 PM · 2 分钟