kratos的jwt中间件仅负责token解析与基础校验(签名、过期、issuer/audience),不自动关联角色或执行权限规则;必须显式配置 signing key 和 signing method,并通过自定义中间件(如对接casbin)实现细粒度授权。

Kratos 本身不内置 RBAC 或 ABAC 等完整权限模型,但提供了开箱即用的 jwt 鉴权中间件和灵活的 Middleware 接口,鉴权逻辑必须由你自行决定“谁有权限访问什么”——框架只负责拦截、解析、透传和拒绝。
kratos 的 jwt 中间件怎么配才真正生效
它只做 token 解析和基础校验(签名、过期、Issuer/Audience),**不会自动关联用户角色或检查权限规则**。常见错误是以为加了中间件就等于鉴权完成,结果所有接口都放行或全拒。
- 必须显式调用
jwt.New()并传入jwt.WithSigningKey(),否则会 panic 报错signing key is required -
jwt.WithSigningMethod(jwt.SigningMethodHS256)要和签发 token 时一致,否则返回token is invalid - 中间件默认从
Authorization: Bearer <token></token>提取,若前端用X-Token头,得自己写 wrapper 包一层jwt.ParseToken - 解析后的
*jwt.Token会存到ctx.Value,后续 handler 里要用jwt.FromContext(r.Context())拿,不是自动注入 struct 字段
如何把 JWT 用户信息对接到 Casbin 做细粒度权限控制
Casbin 是 Kratos 官方 example 中推荐的权限引擎(见 github.com/go-kratos/examples/casbin),但它和 jwt 中间件是解耦的:前者管“能做什么”,后者只管“是不是本人”。两者要串联,靠的是自定义中间件。
- 在 jwt 中间件之后,再挂一个
casbinMiddleware,从 ctx 取出用户 ID 或 role,再调enforcer.Enforce(sub, obj, act) -
sub通常是user.ID或user.Role,obj建议用r.URL.Path+r.Method拼成/v1/users:GET这种格式,便于策略复用 - 注意 Casbin 初始化要早于 HTTP server 启动,否则中间件里
enforcer是 nil;建议在wire.go里通过provider注入 - 策略存储别硬编码用
string,生产环境务必用gorm-adapter或redis-adapter,否则改权限要重启服务
为什么 Zanzibar/OpenFGA 不适合直接嵌入 Kratos HTTP handler
Zanzibar 是服务化架构,OpenFGA 是其开源实现,它们本质是独立运行的授权服务(HTTP/gRPC API),不是 Go 库。直接在 Kratos handler 里同步调用 OpenFGA 的 Check 接口,会引入强依赖和延迟风险。
- 网络超时未设,默认可能卡住整个请求(Go 默认 http.Client 没 timeout)
- OpenFGA 的
store_id和model_id需要和业务服务对齐,比如用户资源user:123、文章post:456,这些 ID 格式要在 Kratos service 层提前构造好,不能靠字符串拼接 - 高频 Check 场景(如列表页每条数据都要鉴权)必须加本地缓存(如
bigcache),key 建议为user_id:resource_type:resource_id:action - Kratos 的
http.Server和grpc.Server共享中间件链,但 OpenFGA 只支持 HTTP/GRPC client,gRPC gateway 场景下要注意 header 透传(如X-User-ID)
自定义鉴权中间件里最容易漏掉的三件事
很多人写完 func Authz(next http.Handler) http.Handler 就以为结束了,但线上常因以下细节出问题:
- 没处理 OPTIONS 预检请求:浏览器 CORS 会先发 OPTIONS,此时若中间件直接 return 401,前端拿不到
Access-Control-Allow-Origin,导致跨域失败 - 错误响应没统一格式:JWT 过期返回
401 {"error":"token expired"},Casbin 拒绝却返回403 {"code":403,"message":"forbidden"},前端鉴权逻辑要写两套 - 日志没打关键字段:只记
"auth failed"没用,至少要记录user_id、path、method、reason(token invalid / policy denied / user not found),否则排查权限问题像盲人摸象
鉴权不是加个中间件就完事,而是要明确「认证(Authentication)」和「授权(Authorization)」的分界:jwt 负责前者,Casbin/OpenFGA/Zanzibar 风格系统负责后者。Kratos 给你的是胶水,不是成品——粘得牢不牢,取决于你怎么设计 sub/obj/act 的语义、怎么兜底网络异常、以及是否让每一次拒绝都有据可查。











