fix: 对齐 authz 认证链路

This commit is contained in:
zetaloop
2026-04-05 12:06:39 +08:00
parent dc87df28a4
commit 384471edca
9 changed files with 864 additions and 58 deletions
+25 -23
View File
@@ -4,7 +4,7 @@
- Envoy 不直接调用业务 proto 方法。
- 新增一个内部服务 `authz-adapter`,实现 Envoy 标准 gRPC 鉴权接口。
- `authz-adapter` 再调用现有 `user-rpc.ValidateToken` 完成鉴权
- `authz-adapter` 再调用现有 `user-rpc.ValidateToken` 完成会话态二次校验
---
@@ -54,13 +54,15 @@ func (s *server) Check(ctx context.Context, req *authv3.CheckRequest) (*authv3.C
}
path := httpReq.GetPath()
method := strings.ToUpper(httpReq.GetMethod())
// 放行公共接口(探针、登录/注册、发送验证码)
if path == "/healthz" ||
path == "/api/users/login" ||
path == "/api/users/register" ||
path == "/api/email/verification-code/send" {
path == "/api/v1/auth/login" ||
path == "/api/v1/auth/register" ||
path == "/api/v1/auth/forgot-password" ||
path == "/api/v1/auth/reset-password" ||
path == "/api/v1/auth/forgot-password/send" ||
path == "/api/v1/email/verification-code/send" {
return allow(nil), nil
}
@@ -69,12 +71,17 @@ func (s *server) Check(ctx context.Context, req *authv3.CheckRequest) (*authv3.C
return deny(401, "missing token cookie"), nil
}
userID, err := parseUserIDFromPath(path)
if err != nil {
return deny(401, "invalid user id in path"), nil
userIDHeader := getHeader(httpReq.GetHeaders(), "x-auth-user-id")
if userIDHeader == "" {
return deny(401, "missing x-auth-user-id header"), nil
}
// 调用你现有业务 RPC
userID, err := strconv.ParseInt(userIDHeader, 10, 64)
if err != nil {
return deny(401, "invalid x-auth-user-id"), nil
}
// 调用现有业务 RPC 做会话态二次校验
vt, err := s.userRpc.ValidateToken(ctx, &userpb.ValidateTokenReq{
Token: token,
UserId: userID,
@@ -89,10 +96,7 @@ func (s *server) Check(ctx context.Context, req *authv3.CheckRequest) (*authv3.C
Header: &core.HeaderValue{Key: "x-auth-user-id", Value: strconv.FormatInt(vt.UserId, 10)},
},
{
Header: &core.HeaderValue{Key: "x-auth-role-type", Value: strconv.FormatInt(vt.RoleType, 10)},
},
{
Header: &core.HeaderValue{Key: "x-auth-method", Value: method},
Header: &core.HeaderValue{Key: "x-auth-role-type", Value: vt.RoleType},
},
}
@@ -135,15 +139,13 @@ func extractCookie(headers map[string]string, name string) string {
return ""
}
func parseUserIDFromPath(path string) (int64, error) {
// 仅示例:请按你的真实路由解析,或改为从 token claim 取 userId
seg := strings.Split(strings.Trim(path, "/"), "/")
for i := 0; i < len(seg); i++ {
if seg[i] == "users" && i+1 < len(seg) {
return strconv.ParseInt(seg[i+1], 10, 64)
func getHeader(headers map[string]string, name string) string {
for k, v := range headers {
if strings.EqualFold(k, name) {
return v
}
}
return 0, strconv.ErrSyntax
return ""
}
func main() {
@@ -211,8 +213,8 @@ func main() {
- 无 token -> 401
- token 无效/过期 -> 401
- 权限不足 -> 403
5. 透传统一鉴权头:`x-auth-user-id``x-auth-role-type`
6. 灰度建议:先仅对 `/api/users` 开启,再扩展到 `/api/email`
5. `jwt_authn` 先注入 `x-auth-user-id``x-auth-is-admin`,再由 adapter 透传 `x-auth-user-id``x-auth-role-type`
6. 灰度建议:先仅对 `/api/v1/auth` `/api/v1/email` 验证链路,再逐步扩展到其它业务路径
> 实践建议:若保留 K8s `readiness/liveness` 探针使用 `/healthz`,请确保该路径在 `ext_authz` 上也放行,否则会出现探针 403 导致 Pod 重启。
@@ -221,7 +223,7 @@ func main() {
## 5) 与当前 `jwt_authn` 的关系
- 可以并存:
-`jwt_authn` 快速验签
-`jwt_authn` 快速验签并注入 claim header
-`ext_authz` 做 Redis 会话态、黑名单、细粒度权限
- 也可以只保留 `ext_authz`(由 adapter 内完成全部逻辑)。