Token验证必须放在中间件中统一处理,解析Authorization Header、校验JWT签名与有效期、注入claims到context;密钥须从环境变量或配置加载且长度≥32字节;Refresh Token需独立管理并一次生效;权限校验须在handler内二次执行。

Token 验证逻辑必须放在中间件里,不能写在每个 handler 中
重复校验 Token 会导致代码冗余、权限逻辑分散,且容易漏掉某个接口。Golang 的 http.Handler 链天然适合用中间件统一拦截——所有请求先过验证,再放行到业务逻辑。
实操建议:
- 定义一个接受
http.Handler并返回新http.Handler的函数,比如authMiddleware - 在中间件中解析 Authorization Header:提取
Bearer后的字符串 - 调用
jwt.Parse(用 github.com/golang-jwt/jwt/v5)验证签名和有效期;失败则直接写入401 Unauthorized并 return - 验证通过后,把解析出的
claims(如用户 ID、角色)注入request.Context,后续 handler 用r.Context().Value()取
JWT 签名密钥不能硬编码,必须从环境变量或配置文件加载
硬编码密钥(比如写死 var secret = "my-secret")等于把门锁钥匙贴在门上。一旦镜像泄露或代码公开,所有 Token 都可被伪造。
实操建议:
- 使用
os.Getenv("JWT_SECRET")读取,启动时确保容器或进程已设置该变量 - 若用 viper,配置项名应为
jwt.secret,类型为 string,且需非空校验 - 密钥长度建议 ≥ 32 字节;若用
HS256,短密钥易被暴力破解;改用RS256时,私钥必须安全存储,公钥用于验证
Token 过期后刷新机制要区分「自动续期」和「强制重登录」
单纯依赖 JWT 过期时间(exp)会导致用户体验断层:用户正在填表单,Token 突然失效,提交直接 401。但无条件刷新又削弱安全性。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
实操建议:
- 签发 Token 时设两个时间:
exp(短,如 15m)和refresh_exp(长,如 7d),后者存在独立字段或 Redis 中 - 提供
/auth/refresh接口,只接受带有效 Refresh Token 的请求,验证通过后签发新 Access Token - Access Token 不支持刷新——它一旦过期就必须走 Refresh 流程;Refresh Token 用一次即失效(或绑定设备指纹)
- 前端需监听 401 响应,若响应体含
{"error": "token_expired"},自动调/auth/refresh,成功后再重发原请求
Role-based 权限检查不能只靠中间件,必须在 handler 内二次校验
中间件只能保证“是登录用户”,不能替代业务级权限控制。比如管理员能删文章,编辑只能改自己写的——这个判断必须落在具体 handler 里,否则会越权。
实操建议:
- 中间件只解析并注入
userID和role(如"admin"或"editor")到 context - 在删除文章的 handler 中,先查数据库确认该文章
author_id == userID,再根据role决定是否允许删除 - 避免用字符串比较做权限(如
if role == "admin"),推荐定义常量const RoleAdmin = "admin",或用 map 做白名单检查 - 敏感操作(如删除账号、修改密码)建议额外加二次确认字段(如
X-Confirm: delete-accountheader)
关键点在于:Token 验证是入口安检,权限判断是房间门锁——前者拦住没票的人,后者确保有票的人只进该进的房间。很多人卡在把两者混为一谈,或者把权限逻辑堆到中间件里,结果改个角色就得动全局代码。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










