文档目录
错误处理与响应

简介

本技术文档聚焦于认证错误处理系统,覆盖未登录(401)与无权限(403)的识别、处理流程与统一响应格式;说明国际化错误消息策略;阐述异常捕获机制(全局异常处理器与自定义异常类型);并给出错误日志记录、监控告警与故障诊断建议,以及常见认证错误的排查步骤与解决方案示例。

项目结构

认证错误处理贯穿“中间件鉴权 → 业务控制器 → 统一响应封装 → 异常短路 → 内核发送”的全链路:

  • API 端通过 UserAuthMiddleware 在 HTTP 边界解析 token、判定登录态与工作身份,失败时直接返回标准 JSON 错误并终止请求。
  • 后台通过 AuthMiddleware 恢复管理员会话,未登录时抛出 HttpResponseException 重定向至登录页。
  • 业务控制器在需要工作端权限时调用统一响应工厂抛出携带标准错误码的异常或直接返回错误响应。
  • ApiResponse 提供统一的信封结构与 request_id 追踪,确保前后端一致的错误契约。
  • 云服务 API 的 JsonResponse 对 4xx/5xx 进行分级日志记录,便于监控与告警。
graph TB
Client["客户端"] --> API["API 入口"]
API --> MW["UserAuthMiddleware<br/>认证与授权"]
MW --> |通过| Ctrl["业务控制器"]
MW --> |拒绝| Resp401["统一 401 响应"]
Ctrl --> |业务校验| Resp403["统一 403 响应"]
Ctrl --> |成功| Resp200["统一 200 响应"]
Resp401 --> Log["日志记录"]
Resp403 --> Log
Resp200 --> Log

图表来源

  • UserAuthMiddleware.php:47-92
  • ApiResponse.php:74-144
  • JsonResponse.php:31-57

章节来源

  • UserAuthMiddleware.php:1-94
  • ApiResponse.php:1-188
  • JsonResponse.php:1-57

核心组件

  • 统一业务错误码:ApiCodes 定义了 UNAUTHORIZED、AUTH_REQUIRED、FORBIDDEN、NOT_FOUND、QUOTA_EXCEEDED、RATE_LIMITED、SERVER_ERROR 等常量,作为对外契约,客户端已硬编码这些字符串值,不得随意改名。
  • 统一响应工厂:ApiResponse 输出固定信封 {code, message, data, errors, request_id},并提供 success/error/throwSuccess/throwError 等方法,保证成功与失败路径的一致性。
  • 异常短路:HttpResponseException 用于在服务层或中间件中携带 Response 短路到内核发送,避免继续执行后续逻辑。
  • 认证中间件:
    • API 端 UserAuthMiddleware:从 Authorization: Bearer 提取 token,解析登录态;未登录返回 401,无 work 身份返回 403。
    • 后台 AuthMiddleware:恢复管理员会话,未登录抛异常跳转登录页。
  • 云服务 API 日志:JsonResponse 对 4xx/5xx 分别以 warning/error 级别记录,便于监控告警。

章节来源

  • ApiCodes.php:21-74
  • ApiResponse.php:23-144
  • HttpResponseException.php:21-53
  • UserAuthMiddleware.php:25-92
  • AuthMiddleware.php:24-50
  • JsonResponse.php:31-57

架构总览

下图展示认证错误处理的端到端流程:从请求进入、中间件鉴权、业务权限校验、统一响应封装、异常短路到最终发送与日志记录。

sequenceDiagram
participant C as "客户端"
participant A as "API 入口"
participant M as "UserAuthMiddleware"
participant S as "业务控制器"
participant R as "ApiResponse"
participant L as "日志"
C->>A : 发起受保护接口请求
A->>M : 解析 Authorization : Bearer
M->>M : 解析登录态 / 工作身份
alt 未登录
M->>R : error(UNAUTHORIZED, 401)
R-->>C : 401 标准响应
R->>L : 记录 warning
else 无工作身份
M->>R : error(FORBIDDEN, 403)
R-->>C : 403 标准响应
R->>L : 记录 warning
else 通过
M->>S : 注入用户上下文
S->>S : 业务权限校验
alt 校验失败
S->>R : error(FORBIDDEN, 403)
R-->>C : 403 标准响应
R->>L : 记录 warning
else 成功
S->>R : success(data)
R-->>C : 200 标准响应
R->>L : 可选记录
end
end

图表来源

  • UserAuthMiddleware.php:47-92
  • ApiResponse.php:92-144
  • JsonResponse.php:31-57

详细组件分析

统一错误码与响应信封

  • 错误码定义集中在 ApiCodes,涵盖认证、授权、资源、配额、限流与服务端错误等场景,保持前后端契约稳定。
  • ApiResponse.payload 构造标准信封,包含 code、message、data、errors、request_id;空数组会被标准化为对象,避免前端解析差异。
  • 成功与失败路径均通过 ApiResponse.success/error 或 throwSuccess/throwError 生成响应,确保一致性。
classDiagram
class ApiCodes {
+OK
+BUSINESS_RULE_VIOLATION
+INVALID_PARAMS
+VALIDATION_FAILED
+UNAUTHORIZED
+AUTH_REQUIRED
+FORBIDDEN
+NOT_FOUND
+QUOTA_EXCEEDED
+RATE_LIMITED
+SERVER_ERROR
+AI_CONFIG_UNAVAILABLE
+CHAT_NOT_FOUND
+CHAT_CREATE_FAILED
+CHAT_SAVE_FAILED
}
class ApiResponse {
+payload(code, message, data, errors) array
+success(data, message) JsonResponse
+error(code, message, errors, httpStatus, data) JsonResponse
+throwSuccess(data, message) never
+throwError(code, message, errors, httpStatus, data) never
-normalizeObjectLike(value) mixed
-generateRequestId() string
}
ApiCodes <.. ApiResponse : "使用"

图表来源

  • ApiCodes.php:21-74
  • ApiResponse.php:65-186

章节来源

  • ApiCodes.php:21-74
  • ApiResponse.php:65-186

API 端认证中间件(401/403 处理)

  • 从 Authorization: Bearer 提取 token,调用 auth('api')->resolveUserContext 解析登录态。
  • 未登录:rejectUnauthenticated 返回 401,消息来自语言包,若缺失则回退键名。
  • 无工作身份:rejectForbidden 返回 403,消息同样来自语言包。
  • 鉴权模式配置位于 api/init/middleware.php,按模块登记 required/optional/public,强制新模块显式声明鉴权级别。
flowchart TD
Start(["请求进入"]) --> Parse["解析 Authorization: Bearer"]
Parse --> Resolve{"解析登录态成功?"}
Resolve --> |否| Reject401["返回 401<br/>UNAUTHORIZED"]
Resolve --> |是| CheckWork{"具备工作身份?"}
CheckWork --> |否| Reject403["返回 403<br/>FORBIDDEN"]
CheckWork --> |是| Next["注入上下文并放行"]

图表来源

  • UserAuthMiddleware.php:47-92
  • middleware.php:18-51

章节来源

  • UserAuthMiddleware.php:25-92
  • middleware.php:18-51

后台认证中间件(401 重定向)

  • 通过 auth('admin')->restoreFromSession 恢复管理员会话。
  • 未登录时抛出 HttpResponseException,携带 redirect 响应跳转至 admin.login。
  • 免登入口由路由级 withoutMiddleware 声明式豁免,不在中间件内硬编码白名单。
sequenceDiagram
participant Admin as "后台请求"
participant AMW as "AuthMiddleware"
participant Core as "内核"
Admin->>AMW : 访问受保护页面
AMW->>AMW : restoreFromSession(ip)
alt 未登录
AMW->>Core : 抛出 HttpResponseException(redirect 到登录页)
Core-->>Admin : 重定向到登录页
else 已登录
AMW-->>Admin : 放行到控制器
end

图表来源

  • AuthMiddleware.php:42-50
  • HttpResponseException.php:21-53

章节来源

  • AuthMiddleware.php:24-50
  • HttpResponseException.php:21-53

业务控制器中的权限校验(403 示例)

  • 售后 WorkController:checkPermission 校验工作端权限与模块可用性,失败返回 403。
  • 订单 WorkController:mustLoginAndPermission 先校验登录态(401),再校验工作权限(403)。
  • 控制器通过 ApiResponse::throwError 或 ApiResponse::error 抛出/返回标准错误响应,确保短路或统一封装。
flowchart TD
Enter(["进入控制器方法"]) --> LoginCheck{"是否已登录?"}
LoginCheck --> |否| Throw401["抛出 401<br/>UNAUTHORIZED"]
LoginCheck --> |是| PermCheck{"是否有工作权限?"}
PermCheck --> |否| Throw403["抛出 403<br/>FORBIDDEN"]
PermCheck --> |是| Continue["执行业务逻辑"]

图表来源

  • WorkController.php(售后):52-63
  • WorkController.php(订单):178-190
  • ApiResponse.php:112-144

章节来源

  • WorkController.php(售后):47-80
  • WorkController.php(订单):168-191
  • ApiResponse.php:92-144

统一响应与日志记录

  • ApiResponse.payload 生成标准信封,包含 request_id 用于跨层追踪。
  • 云服务 API 的 JsonResponse 对 4xx 记录 warning、5xx 记录 error,便于监控告警与问题定位。
  • 建议在关键认证失败点附加 context(如 channel、http_status、message、data),提升可观测性。
graph LR
Err["认证失败"] --> Payload["ApiResponse.payload"]
Payload --> Json["JsonResponse.send"]
Json --> Log["Log.warning / Log.error"]

图表来源

  • ApiResponse.php:65-144
  • JsonResponse.php:31-57

章节来源

  • ApiResponse.php:65-144
  • JsonResponse.php:31-57

依赖关系分析

  • ApiResponse 依赖 ApiCodes 提供稳定的业务码常量。
  • UserAuthMiddleware 依赖 ApiResponse 与语言包 lang() 提供国际化消息。
  • 后台 AuthMiddleware 依赖 HttpResponseException 实现重定向短路。
  • 云服务 API 的 JsonResponse 依赖 Log 进行分级记录。
graph TB
ApiCodes["ApiCodes"] --> ApiResponse["ApiResponse"]
ApiResponse --> UserAuthMW["UserAuthMiddleware"]
ApiResponse --> Controllers["业务控制器"]
AuthMW["AuthMiddleware"] --> HttpResponseEx["HttpResponseException"]
JsonResponse["JsonResponse"] --> Log["Log"]

图表来源

  • ApiCodes.php:21-74
  • ApiResponse.php:65-144
  • UserAuthMiddleware.php:47-92
  • AuthMiddleware.php:42-50
  • JsonResponse.php:31-57

章节来源

  • ApiCodes.php:21-74
  • ApiResponse.php:65-144
  • UserAuthMiddleware.php:47-92
  • AuthMiddleware.php:42-50
  • JsonResponse.php:31-57

性能考虑

  • 中间件尽早拦截无效请求,减少后端业务处理开销。
  • 统一响应工厂避免重复构造错误数据,降低序列化成本。
  • 日志记录仅对 4xx/5xx 进行分级记录,避免过度 I/O 影响吞吐。
  • request_id 在同一请求中复用,减少重复生成开销。

故障排查指南

  • 未登录(401)
    • 检查 Authorization: Bearer 是否正确传递。
    • 确认 api/init/middleware.php 中对应模块的鉴权模式是否为 required。
    • 查看 UserAuthMiddleware.rejectUnauthenticated 返回的消息与日志。
  • 无权限(403)
    • 检查工作端权限校验逻辑(如 checkPermission、mustLoginAndPermission)。
    • 确认模块是否启用且用户具备相应工作身份。
    • 查看 ApiResponse::throwError 或 ::error 的调用位置与参数。
  • 国际化消息
    • 检查 languages/zh_cn/common.lang.php 是否存在 login_timeout、work_no_permission 等键。
    • 若缺失,语言包会回退键名,需补充翻译键以确保友好提示。
  • 日志与监控
    • 关注 _/.api/lib/Log.php 的 warning/error 级别记录。
    • 结合 request_id 在日志中追踪同一请求的错误链路。

章节来源

  • UserAuthMiddleware.php:77-92
  • WorkController.php(订单):178-190
  • common.lang.php:64-64
  • JsonResponse.php:31-57

结论

本项目通过集中化的错误码定义、统一的响应信封、中间件前置鉴权与异常短路机制,实现了清晰、稳定、可观测的认证错误处理体系。401 与 403 的处理路径明确,国际化消息支持完善,日志记录分级合理,便于监控告警与故障诊断。遵循本文档的实践可显著提升认证相关问题的定位效率与用户体验。

附录

  • 统一响应信封字段说明
    • code:字符串业务码,成功固定为 OK。
    • message:人类可读提示文案,客户端不应依赖此分支做判断。
    • data:业务数据载体,失败时固定为空对象。
    • errors:字段错误集合,无字段错误时固定为空对象。
    • request_id:请求追踪 ID,便于跨层定位问题。
添加日期:2026-10-05