Kratos本身不内置鉴权逻辑,仅提供JWT认证中间件和Middleware接口;必须自行集成Casbin等引擎实现细粒度授权,因jwt.Server只校验token合法性,不判断“用户能否访问某路径”。

直接上结论:Kratos 本身不内置鉴权逻辑,只提供认证(如 jwt.Server)和中间件挂载能力;真正的鉴权必须自己选型集成——Casbin、OPA、Zanzibar 都可落地,但生产环境最常用、最轻量、与 Kratos 耦合度最低的是 Casbin。
为什么不能只用 jwt.Server 做鉴权
jwt.Server 只负责解析并校验令牌合法性,它能告诉你「这个 token 是谁签发的、有没有过期、签名对不对」,但完全不回答「这个用户能不能访问 /admin/users 这个路径」。一旦你把权限判断硬编码进 handler,就会出现:角色改了要重编译、策略变更是改代码、多服务间权限不一致。
- 典型错误现象:
ErrTokenExpired能捕获,但if user.Role != "admin"写满整个 service 层 - JWT Claims 里塞
roles字段只是传递身份上下文,不是授权决策本身 - Kratos 的
middleware/auth/jwt/jwt.go没有预留策略钩子,它只做「放行 or 拒绝 token」,不介入「放行后能干什么」
Casbin 在 Kratos 中的最小可行集成
不需要改 Kratos 启动流程,也不用侵入 transport 层——在每个需要鉴权的 HTTP handler 开头加一行 e.Enforce(...) 即可。模型和策略建议从文件起步,避免早期引入数据库依赖。
- 安装:
go get github.com/casbin/casbin/v2 - 初始化 enforcer(建议放在
internal/conf/conf.go或internal/service/init.go):enforcer := casbin.NewEnforcer("model.conf", "policy.csv") - 在 handler 中使用(注意三元组顺序必须是
sub, obj, act):if ok, _ := enforcer.Enforce(user.Username, r.URL.Path, r.Method); !ok { http.Error(w, "forbidden", http.StatusForbidden) return } -
model.conf推荐 RBAC with resource roles:[request_definition] r = sub, obj, act [policy_definition] p = sub, obj, act [role_definition] g = _, _ [policy_effect] e = some(where (p.eft == allow)) [matchers] m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
HTTP 中间件里怎么安全透传用户身份
Kratos 的 HTTP 中间件默认拿不到 JWT 解析出的用户信息,因为 jwt.Server 把数据塞进了 http.Request.Context(),但你写的中间件如果没显式调用 req.Context().Value(...),就等于没接住。
- 常见错误:在 middleware 里直接用
transport.HTTPContext().Value(auth.Key)——这是个空 context,不是 request context - 正确做法:在自定义鉴权中间件中,先从 request context 取值:
user, ok := req.Context().Value(auth.Key).(*jwt.Token) if !ok { http.Error(w, "unauthorized", http.StatusUnauthorized) return } - 再把用户标识(如
user.Claims.(CustomClaims).Username)传给后续 handler,或直接在这里调enforcer.Enforce() - 务必检查
CustomClaims类型断言是否成功,否则 panic 会直接 crash 整个 HTTP server
别忽略的两个复杂点
一是 Casbin 策略热更新:文件模式下改了 policy.csv 不会自动 reload,得手动调 enforcer.LoadPolicy();二是多服务共享权限时,模型必须统一——比如所有服务都用 sub, obj, act 三元组,但 obj 格式要是全局限定名(service.user:/v1/users),否则 A 服务的策略在 B 服务里可能匹配失效。


















