Skip to content

058. 认证中间件与接口文档 Token 调试 ​

学习目标 ​

这一节完成认证中间件,并处理接口文档里的 token 调试体验。

学完后,你应该能理解:

  • 中间件链为什么像 Koa 洋葱模型;
  • 认证中间件要处理哪些分支;
  • 异常中间件为什么要放在认证中间件外层;
  • 白名单接口如何跳过 token 校验;
  • Swagger 为什么需要全局安全依赖;
  • 导入路径为什么要统一。

计时中间件 ​

先用一个简单计时中间件理解中间件结构。

它在请求开始时记录时间。

业务接口执行完后,再计算耗时。

最后把耗时写到响应头里。

例如响应头里出现:

txt
x-process-time

这说明中间件确实参与了请求流程。

中间件必须返回响应 ​

中间件里调用 call_next(request) 后,要把 response 返回出去。

如果只 await call_next(request),但没有 return response,后续链路会断。

最终可能出现类似“None 不能被调用或等待”的错误。

对 JS 开发者来说,可以把它理解成 Express/Koa 中间件里忘记把结果继续返回。

认证中间件的职责 ​

认证中间件要处理很多分支。

它通常需要:

  • 初始化 request.state.user;
  • 放行预检请求;
  • 判断当前路径是否在白名单;
  • 从请求头读取 Authorization;
  • 解析 bearer token;
  • 解码 token payload;
  • 判断是否开启全局 token 校验;
  • 校验 API token 类型;
  • 查询当前用户;
  • 判断用户状态是否有效;
  • 把用户写入 request.state.user。

认证中间件不是只做一行 token 判断。

它是全局入口的安全门。

预检请求 ​

浏览器跨域请求可能先发 OPTIONS 预检请求。

预检请求不应该被普通 token 校验挡住。

否则真正的业务请求还没发出,浏览器就已经因为跨域失败而终止。

所以中间件里要优先处理预检请求。

白名单接口 ​

白名单接口直接放行。

例如:

  • 登录;
  • 注册;
  • 激活账号;
  • 刷新 token;
  • 文档页;
  • 静态资源;
  • 测试接口。

白名单之外的接口,才进入 token 校验流程。

401 与 403 ​

没有 token、token 无效、token 过期,通常返回 401。

用户存在但状态不可用,例如未激活或被禁用,可以返回 403。

这两个状态码含义不同:

  • 401: 认证失败;
  • 403: 已识别身份,但不允许访问。

区分它们有助于前端做正确处理。

异常中间件 ​

如果认证中间件里抛出 HTTPException,默认可能被包装成 500。

这样前端只能看到 Internal Server Error。

异常中间件负责把预期内的 HTTPException 转成统一 JSON 响应,并保留原状态码。

例如 token 无效时,前端应该看到 401,而不是 500。

中间件顺序 ​

中间件是从外到内执行请求,再从内到外返回响应。

可以把它理解成洋葱模型。

如果异常中间件要捕获认证中间件里的错误,它必须包在认证中间件外层。

顺序放错,认证中间件抛出的异常就不会被它捕获。

所以中间件顺序不是随便写的。

全局 token 认证 ​

认证中间件实现后,大部分接口都会被 token 保护。

白名单接口仍然可以不带 token 访问。

例如测试白名单路径可以直接返回。

非白名单接口不带 token 时,会返回 token 无效或过期。

Swagger 文档里的锁标记 ​

FastAPI 文档会根据安全依赖显示锁标记和授权按钮。

如果每个接口都手动加安全依赖,文档显示会比较准确,但代码会重复。

项目里可以在应用初始化时添加全局安全依赖。

这样 Swagger 里所有接口都会显示需要认证,并且授权后调试接口会自动带 token。

全局安全依赖不会替代中间件 ​

这里的全局安全依赖主要是为了文档调试体验。

真正控制接口是否放行的是认证中间件和白名单逻辑。

所以白名单接口即使文档上显示锁,也仍然可以按中间件规则放行。

导入路径统一 ​

后端项目里导入路径要统一。

如果 IDE 把某个目录标记成源码目录,导入可以少写一层前缀。

但不同同学环境不一致时,就可能出现导入报错。

为了减少差异,课程代码会把导入路径统一成带应用前缀的写法。

这样更适合跨环境运行。

这一节的重点 ​

这一节把认证从局部依赖推进到全局中间件。

你需要记住:

  • 中间件必须返回 response;
  • 认证中间件要处理白名单、预检、token 和用户状态;
  • 异常中间件要放在能包住认证中间件的位置;
  • Swagger 的授权按钮服务于调试;
  • 导入路径要统一,避免依赖 IDE 私有设置。

AI Agent 课程学习文档。