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.
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:
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
CheckPasswordHashverifizieren - 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}:
- 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.Pathohne 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
Noch keine Kommentare.