package server import ( "context" "net/http" "strings" "agent-system-backend/internal/store" ) // ownerCtxKey 携带租户身份(认证中间件注入;未启用认证 = store.OwnerDefault)。 type ownerCtxKey struct{} // Authenticator 是 API key 认证(阶段 1:user 即租户)。 // Enabled=false(嵌入式档默认,回环本地单用户)时全部请求回落默认租户。 // SSE 的 EventSource 无法带 Authorization 头,允许 ?key= 查询参数兜底。 type Authenticator struct { st *store.Store Enabled bool } func NewAuthenticator(st *store.Store, enabled bool) *Authenticator { return &Authenticator{st: st, Enabled: enabled} } func (a *Authenticator) Middleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if a == nil || !a.Enabled { next.ServeHTTP(w, r.WithContext(withOwner(r, store.OwnerDefault))) return } key := bearerKey(r) if key == "" { key = r.URL.Query().Get("key") } if key == "" { http.Error(w, "unauthorized: missing API key (Authorization: Bearer )", http.StatusUnauthorized) return } owner, ok := a.st.AuthOwner(key) if !ok { http.Error(w, "unauthorized: invalid or revoked API key", http.StatusUnauthorized) return } next.ServeHTTP(w, r.WithContext(withOwner(r, owner))) }) } func withOwner(r *http.Request, owner string) context.Context { return context.WithValue(r.Context(), ownerCtxKey{}, owner) } func bearerKey(r *http.Request) string { h := r.Header.Get("Authorization") if strings.HasPrefix(h, "Bearer ") { return strings.TrimSpace(strings.TrimPrefix(h, "Bearer ")) } return "" } // owner 从请求上下文取租户身份(未注入回落默认)。 func (s *Server) owner(r *http.Request) string { if v, ok := r.Context().Value(ownerCtxKey{}).(string); ok && v != "" { return v } return store.OwnerDefault }