package middleware import ( "net/http" "strings" "github.com/gin-gonic/gin" "github.com/sundynix/sundynix-gateway/internal/auth" ) // AuthFromHeaderOrQuery 是给「公开 by-id」端点(SSE 流 / 报告下载)用的强制鉴权。 // 这些端点由 EventSource / 发起,**带不了 Authorization 头**——此前只靠随机 // task_id 寻址、无 authz、无租户过滤(capability-URL,泄露即无第二道门)。 // 本中间件先读 Bearer 头、没有再读 `?token=` / `?access_token=` 查询参数(EventSource 能带 query), // 校验通过注入 CtxUserID(同 Auth),失败即 401。归属校验由各 handler 用 uid 再做(见 requireTaskOwner)。 func AuthFromHeaderOrQuery() gin.HandlerFunc { return func(c *gin.Context) { tok := "" if h := c.GetHeader("Authorization"); strings.HasPrefix(h, "Bearer ") { tok = strings.TrimSpace(h[len("Bearer "):]) } if tok == "" { tok = c.Query("token") } if tok == "" { tok = c.Query("access_token") } uid, err := auth.Parse(tok) if err != nil || uid == "" { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "需要登录"}) return } c.Set(CtxUserID, uid) c.Next() } }