package middleware import ( "net/http" "strings" "ezops/model" "ezops/pkg/agentauth" "github.com/gin-gonic/gin" "gorm.io/gorm" ) const agentCredentialContextKey = "agentCredential" // AgentAuth 在兼容阶段识别新 Token,强制阶段拒绝旧的匿名和用户 JWT 调用。 // Logan.Li func AgentAuth(db *gorm.DB, enforce bool) gin.HandlerFunc { return func(c *gin.Context) { authHeader := c.GetHeader("Authorization") if authHeader == "" { if enforce { c.AbortWithStatusJSON(http.StatusUnauthorized, model.Response{Code: 401, Message: "未提供 Agent 凭证"}) } return } parts := strings.SplitN(authHeader, " ", 2) if len(parts) == 2 && parts[0] == "Bearer" && strings.HasPrefix(parts[1], "agt_") { credential, err := agentauth.Authenticate(db, parts[1]) if err == nil { c.Set(agentCredentialContextKey, credential) return } c.AbortWithStatusJSON(http.StatusUnauthorized, model.Response{Code: 401, Message: "无效 Agent 凭证"}) return } if enforce { c.AbortWithStatusJSON(http.StatusUnauthorized, model.Response{Code: 401, Message: "无效 Agent 凭证"}) } } } // RequireAgentHostname 校验请求中主机名与凭证绑定主机一致。 // Logan.Li func RequireAgentHostname(c *gin.Context, hostname string) bool { credential, exists := c.Get(agentCredentialContextKey) if !exists { return true } agentCredential, ok := credential.(*model.AgentCredential) if !ok || agentCredential.Hostname != hostname { c.AbortWithStatusJSON(http.StatusForbidden, model.Response{Code: 403, Message: "Agent 凭证与主机不匹配"}) return false } return true }