应使用 net/http 中间件实现请求级身份验证:提取 Authorization 头、解析 JWT、校验签名与过期、存用户信息至 context;配合 chi 路由做路径级权限控制;防范 CSRF/CORS/敏感字段泄露;用 OpenAPI 与 validator 实现精细化输入校验和错误响应。

用 net/http 中间件做请求级身份验证
Go 没有内置的“认证框架”,但你可以用标准库的中间件模式在路由前拦截并校验请求。关键不是加功能,而是把验证逻辑从 handler 里抽出来,避免每个接口都重复写 Authorization 头解析、token 解析、过期检查。
常见错误是直接在 handler 里硬编码校验逻辑,导致无法复用、难以测试、权限逻辑散落各处。正确做法是写一个返回 http.Handler 的函数:
- 提取
Authorization头,校验格式是否为"Bearer" - 调用
jwt.Parse(用github.com/golang-jwt/jwt/v5)验证签名和exp字段 - 解析出用户 ID 或角色后,存入
context.WithValue(r.Context(), key, value) - 校验失败时直接
http.Error(w, "Unauthorized", http.StatusUnauthorized)并 return,不调用 next
这样后续 handler 只需从 r.Context().Value(...) 拿用户信息,不用关心怎么来的。
用 gorilla/mux 或 chi 实现路径级权限控制
单纯鉴权不够,你还得控制“谁能在什么路径上做什么”。net/http 路由太简陋,推荐用 chi——轻量、中间件链清晰、支持路由参数绑定。
立即学习“go语言免费学习笔记(深入)”;
比如管理后台的 /api/users/{id} 需要管理员权限,而普通用户只能访问自己的 /api/users/me:
- 给不同角色定义常量:
const RoleAdmin = "admin"、RoleUser = "user" - 写一个
requireRole(role string)中间件,从 context 取角色,比对失败返回403 - 在注册路由时链式挂载:
router.Get("/users/me", requireRole(RoleUser), userHandler) - 注意:不要在中间件里做 DB 查询,应提前在鉴权中间件中查好角色并塞进 context
防止常见漏洞:CSRF、CORS、敏感字段泄露
REST API 虽不渲染 HTML,但若被浏览器前端调用,仍需防 CSRF;若跨域调用,CORS 配置不当会暴露接口或引发预检失败;返回数据里混入 password_hash 或 api_key 是高频事故。
- CSRF:纯 API 场景下,只要不接收
Cookie认证(改用Authorization: Bearer),且前端不带withCredentials: true,就天然免疫。别为了“统一”强行加 Cookie - CORS:用
rs/cors包,显式设置AllowedOrigins和AllowCredentials: false(除非真需要 Cookie);避免设成*同时开AllowCredentials,这会直接被浏览器拒绝 - 敏感字段:永远不要让 struct 直接序列化返回。用专用的响应 struct(如
UserResponse),只包含前端需要的字段;或用json:"-"或json:"password,omitempty"控制导出
用 swaggo/swag 自动生成 OpenAPI 并启用请求校验
文档不是锦上添花,而是安全边界的一部分。OpenAPI 定义了每个 endpoint 的参数类型、必填项、格式约束(如 email、uuid),配合校验中间件可拦截非法输入,防止注入或越权操作。
- 在 handler 函数上方加
// @Param id path string true "user ID" format(uuid)注释,运行swag init生成docs/docs.go - 用
go-playground/validator/v10校验结构体字段,比如type CreateUserReq struct { Email string `validate:"required,email"` } - 在中间件中调用
validate.Struct(req),错误时返回400和具体字段名,而不是泛泛的 “invalid request” - 注意:OpenAPI 的
securitySchemes定义只是文档说明,不会自动生效,仍需你自己在中间件里实现 token 校验逻辑
最易被忽略的是错误处理粒度——很多人把所有校验失败都扔进一个 400 分支,结果前端无法区分是 ID 格式错、邮箱重复,还是权限不足。按错误类型分状态码、带明确字段提示,才是真安全。










