认证与请求上下文——Middleware / Token / Session 的位置
请求进入服务器后,不是直接进业务——在 Router 之前通常还有一层横向处理:认证、权限、日志、限流。这一条线回答三个问题:① Router / Controller / Middleware 各自的职责是什么、认证放在哪(不是 Controller 的职责);② Connection State(网络层)/ Session(应用层会话)/ Token(凭证)三者怎么区分;③ Controller 不是强制层——职责重复就拆分,没有职责就不要增加层。
一、请求进入服务器后的实际流动顺序
不要把 Router、Controller、认证、Session 当成平级的「层」:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| 客户端 │ │ HTTP Request ▼ ┌─────────────────────┐ │ HTTP Server │ ← 通信协议 └─────────┬───────────┘ ▼ ┌─────────────────────┐ │ Middleware │ ← Token / Session / 日志 / 限流 └─────────┬───────────┘ ▼ ┌─────────────────────┐ │ Router │ ← 找到哪个 Controller └─────────┬───────────┘ ▼ ┌─────────────────────┐ │ Controller │ ← 请求 → 业务参数 └─────────┬───────────┘ ▼ ┌─────────────────────┐ │ Service │ ← 执行业务 └─────────┬───────────┘ ▼ Domain │ Infrastructure
|
二、Router / Controller / Middleware 三个职责
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| Router:找谁——这个请求应该交给谁? GET /users/123 → UserController::get() POST /users → UserController::create() POST /login → AuthController::login()
Controller:怎么调用业务——请求的数据怎么转换成一次业务调用? HTTP Request(path/query/headers/JSON body) ↓ UserController ↓ UserService.get_user(user_id)
Middleware:能不能进来、进来之前要处理什么 Token / Session 认证、权限、日志、限流
|
三个词:
1 2 3 4
| Middleware:能不能进来 Router:找谁 Controller:怎么调用业务 Service:业务怎么做
|
三、Token 认证在哪里?
Token 通常出现在 HTTP → Middleware → Router 之间:
1 2
| GET /users/123 Authorization: Bearer abc123
|
Middleware:
1
| 取 Authorization → 解析 Token → 验证 Token → 得到 UserIdentity → 允许继续
|
如果认证放在每个 Controller 里,就会大量重复:
1 2
| if (!check_token(...)) return unauthorized;
|
认证通常不是 Controller 的职责。
四、Session 又在哪里?
容易混淆的一点:
Session 是服务器保存的「登录状态」;Token 通常是客户端携带的「身份凭证」。
传统 Session 流程:
1 2 3
| 客户端 POST /login → AuthController → AuthService → 验证账号密码 → SessionManager(session_id → user_id) → Set-Cookie: session_id=abc123
|
之后:
1 2
| 客户端 Cookie: session_id=abc123 → HTTP Server → Session Middleware → 查 session → 得到 user_id → 建立当前请求身份 → Router → Controller → Service
|
Session 的管理实现属于基础设施:
1 2 3 4 5
| Infrastructure └── Session ├── SessionManager ├── MemorySessionStore └── RedisSessionStore
|
「当前用户是谁」作为请求上下文向内传递:
1 2 3 4 5
| RequestContext ├── user_id ├── roles ├── permissions └── session_id
|
五、Connection State / Session / Token 三分
三个概念经常一起出现,但不是一回事。
1. Connection State(网络层/服务器运行时)
1 2
| Connection(TCP): Socket + Remote Endpoint + Connected + Read/Write State + Timeout Client State(UDP): IP + Port + LastSeen + Sequence ...
|
2. Session(应用层用户会话状态)
1
| Session: session_id + user_id + login_time + expire_time + permissions
|
一个用户的 Session 可以在网络连接断开后继续存在:
1 2 3
| 连接1:登录 → Session = S123 → 连接关闭 过一会儿 连接2:携带 S123 → 恢复用户会话
|
3. Token(凭证)
1 2
| Token = 客户端拿来证明自己身份/会话的凭证 Session = 服务器保存的会话状态
|
1 2
| 登录 → 服务器验证 → 生成 Token → 返回客户端 客户端以后:请求 Authorization: Bearer xxx → 服务器验证 Token → 得到 user_id → Service
|
两者可以组合:Token → Session ID → 服务器 Session → User
放回服务器架构
1 2 3 4 5 6
| Server ├── Network Socket / Connection State ├── Protocol Decoder / Encoder ├── Request Dispatch ├── Authentication / Session Token + Session └── Business Service
|
Token 和 Session 通常属于业务/应用层,不属于 TCP/UDP 的连接状态。 目录建议:
1 2 3 4 5 6 7 8 9
| server/ ├── network/ connection/ ├── protocol/ ├── router/ ├── handler/ ├── auth/ token/ + session/ ├── service/ ├── domain/ └── infrastructure/
|
不要把 token 塞进 connection/。
UDP 游戏服务器的完整职责链
1
| IP:Port → Client State → Player → Session → Token/Authentication → GameService
|
1 2 3 4 5
| IP:Port → 网络端点 Connection State → 网络通信状态 Session → 用户会话状态 Token → 身份/会话凭证 Player/User → 业务实体
|
六、Controller 不是强制层
如果 Router/请求处理函数已经承担了「请求 → 业务调用」的职责,Controller 就是重复职责,不需要。
CLI 三层:
1 2 3 4 5 6
| CLI ├── 输出层 ├── 命令解析层 └── 调用层 ↓ Service
|
Server 对应:
1 2 3 4 5 6
| Server ├── 通信层 ├── 请求解析/路由层 └── 调用层 ↓ Service
|
甚至可以直接:
1 2 3
| router.post("/process", [](Request request) { return processService.process(request.json()["pid"]); });
|
Token/Session 放在请求进入 Service 之前:
1
| HTTP → Authentication → Router → Service
|
核心原则:
不要因为「服务器通常有 Controller」就必须创建 Controller。职责重复就拆分;没有职责就不要增加层。
七、这一条线的位置
1 2 3 4 5 6 7 8 9 10 11 12
| 系统角色(主题): 07 服务器入口的解构(接受 → 解析 → 分发 → 调用) 09 认证与请求上下文(本线:认证/Token/Session 在入口里的位置)
服务器入口的解构(04-系统角色/07): 07 讲入口骨架的四段(接受/解析/分发/调用) 本线讲的是夹在「接受」和「分发」之间的横向处理(Middleware), 以及贯穿整个请求的「当前用户是谁」(RequestContext)
设计起点(06-设计/01): 服务器的控制面是「协议 + 请求模型」 认证模型(Token/Session)是请求模型的一部分,在设计协议时一起定
|
与 07 的关系:07 的入口骨架是「接受 → 解析 → 分发 → 调用」四段;本线的 Middleware(认证/限流/日志)是夹在接受之后、分发之前的横向处理——它不是骨架的一段,而是每一段之前都可能经过的横切。Token/Session 则是「请求上下文」——认证通过后,把「当前用户是谁」作为 RequestContext 向下传递,Handler/Service 从上下文取身份,而不是每个 Service 自己再查一次。
收束
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 请求进入服务器的实际顺序: HTTP Server → Middleware(认证/限流/日志)→ Router → Controller → Service → Domain
三个职责: Middleware:能不能进来(Token/Session 认证、权限、日志、限流) Router:找谁(URL/命令码 → Controller/Handler) Controller:怎么调用业务(请求 → 业务参数)——不是强制层
Token 与 Session: Token = 客户端携带的身份凭证(Authorization: Bearer xxx) Session = 服务器保存的登录状态(session_id → user_id) 都是应用层概念,不属于网络层连接状态
Connection / Session / Token 三分: Connection State:网络层(Socket + 连接状态 + Timeout) Session:应用层用户会话(登录状态,可跨连接) Token:凭证(证明身份/会话)
Controller 不是强制层: 职责重复就拆分;没有职责就不要增加层 Router/处理函数承担「请求 → 业务调用」时,Controller 可省略
|
认证与请求上下文 = 请求进入业务之前的横向处理:Middleware 管「能不能进来」,Router 管「交给谁」,Token/Session 管「当前用户是谁」并作为请求上下文向下传递。 认证不是 Controller 的职责,Controller 也不是强制层——这是服务器入口骨架(07)之外的横切关注点。