Zurück zur Startseite

Dynamische Routen net/http: DeadDrop-Implementierung

Der Artikel analysiert die Implementierung dynamischer Routen und Cookie-Authentifizierung in purem net/http für den DeadDrop-Service. Manuelles Pfad-Parsing, HMAC-Token, Use-Case-Architektur. Vollständiger Zyklus mit Tests.

net/http: dynamische Routen und Cookie-Auth in DeadDrop
Advertisement 728x90

Dynamische Routen und Cookie-Authentifizierung in net/http: Implementierung von DeadDrop

In Fortsetzung unserer Serie zu reinem net/http implementieren wir dynamisches Routing für den DeadDrop-Dienst. Nutzer können Geheimnisse über Links wie /secret/{id} einsehen. Der Standard-Mux unterstützt bis Go 1.22 keine Pfadparameter, daher schreiben wir unseren eigenen Parser.

Der Handler wird unter /secret/ mit einem abschließenden Schrägstrich registriert – dies erfasst alle Unterpfade. Wir extrahieren die ID manuell aus r.URL.Path.

func extractIDFromPath(path string) (string, bool) {
    const prefix = "/secret/"

    if !strings.HasPrefix(path, prefix) {
        return "", false
    }

    id := strings.TrimPrefix(path, prefix)
    if id == "" || strings.Contains(id, "/") {
        return "", false
    }

    return id, true
}

Die Funktion prüft das Präfix, entfernt es und schließt ungültige IDs (leer oder mit /) aus. Dies bietet grundlegenden Schutz vor fehlerhaften Anfragen.

Google AdInline article slot

SecretHandler mit DI

Wir erstellen eine Handler-Struktur für Dependency Injection:

type SecretHandler struct {
    // Platzhalter für DI
}

func NewSecretHandler() *SecretHandler {
    return &SecretHandler{}
}

func (h *SecretHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    id, ok := url.ExtractIDFromPath(r.URL.Path)
    if !ok {
        http.NotFound(w, r)
        return
    }
    w.Header().Set("Content-Type", "text/plain; charset=utf-8")
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("Angefragtes Geheimnis mit ID: " + id))
}

Registrieren Sie es in router.go: mux.Handle("/secret/", secretHandler). Testen Sie Grenzfälle:

  • /secret/12345/ → 404
  • /secret/ → 404
  • /secret/axQ/233 → 404
  • /secret/ad31H234 → OK mit ID

Anwendungsfall zum Abrufen eines Geheimnisses

Definieren Sie Anfrage und Antwort:

Google AdInline article slot
type GetSecretRequest struct {
    ID       string
    Password string
}

type GetSecretResponse struct {
    ID        string
    Message   string
    FileName  string
    FileExt   string
    HasFile   bool
    ExpiresAt time.Time
}

Anwendungsfall-Logik:

  • Geheimnis aus dem Speicher abrufen
  • Ablaufzeit prüfen (time.After()), abgelaufene löschen
  • Passwort über CheckPasswordHash verifizieren
  • Daten oder Fehler zurückgeben

Cookie-Authentifizierung

Um Dateidownloads zu schützen, implementieren wir Authentifizierung über Cookies. Nach erfolgreicher Passwortprüfung setzen wir ein Session-Cookie mit einem verschlüsselten Zugriffstoken.

  • Vorteile: zustandslos, skalierbar, keine Session-Speicherung
  • Cookie-Parameter: HttpOnly, Secure, SameSite=Strict

Bei Anfrage an /download/{id}:

Google AdInline article slot
  • ID aus dem Pfad extrahieren
  • auth_token-Cookie auslesen
  • Token entschlüsseln und verifizieren (ID + Passwort-Hash + Nonce)
  • Bei Gültigkeit – Datei bereitstellen

Zugriffstoken-Struktur

Das Token wird als base64(ID + ":" + hash + ":" + nonce) gebildet, wobei:

  • hash = HMAC-SHA256(ID + password, secretKey)
  • nonce – eine Einmalnummer zum Schutz vor Replay-Angriffen

Beispielvalidierung:

func validateDownloadToken(id, token string) bool {
    // Token entschlüsseln
    // Hash und Nonce extrahieren
    // HMAC neu berechnen
    // vergleichen
    return true // oder false
}

Vollständiger Geheimnis-Workflow

  • Erstellung: POST /create → ID generieren, Passwort hashen, speichern
  • Anzeige: GET /secret/{id} → Passwort-Eingabeformular
  • Authentifizierung: POST Passwort → Cookie + Weiterleitung
  • Download: GET /download/{id} → Cookie prüfen → Datei
  • Bereinigung: TTL abgelaufen → Löschung

UI-Prototyp: Seite mit Passwortfeld, "Öffnen"-Button. Nach Erfolg – Inhalt + Dateilink.

Routing-Tests

| Testpfad | Erwartung | Ergebnis |

|-----------|-------------|--------|

| /secret/123/ | 404 | 404 |

| /secret/ | 404 | 404 |

| /secret/id/with/slash | 404 | 404 |

| /secret/valid123 | OK: "ID: valid123" | OK |

Grenzfälle decken Parser-Sicherheit ab.

Wichtige Punkte

  • Dynamische Routen: manuelle Analyse von r.URL.Path ohne Drittanbieter-Router
  • Sicherheit: ID-Validierung, Schrägstrichprüfungen, TTL für Geheimnisse
  • Authentifizierung: Cookie mit HMAC-Token statt Sessions
  • Architektur: Anwendungsfall + DI, saubere Logik außerhalb Handler
  • Skalierbarkeit: zustandslos, bereit für Clustering

— Editorial Team

Advertisement 728x90

Weiterlesen