认证与请求上下文——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)之外的横切关注点。