feat: Passwortschutz im Server statt im Browser
Ohne gueltiges Passwort gibt der Server weder Seite noch Skript heraus. Das Passwort kommt aus APP_PASSWORD; fehlt die Variable, startet der Server absichtlich nicht. /healthz bleibt passwortfrei, damit die Ueberwachung den geschuetzten Dienst nicht faelschlich fuer ausgefallen haelt.
This commit is contained in:
@@ -144,6 +144,8 @@ Oberfläche laufen nur im echten Browser und werden dort manuell geprüft
|
||||
|
||||
## Produktion
|
||||
|
||||
Zum lokalen Nachschauen ohne Passwort:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
npm run preview
|
||||
@@ -152,6 +154,37 @@ npm run preview
|
||||
`preview` hört auf `PORT` aus der Umgebung (Vorgabe `4173`, falls `PORT`
|
||||
nicht gesetzt ist).
|
||||
|
||||
Im Betrieb läuft stattdessen `server.py` — siehe nächster Abschnitt.
|
||||
|
||||
## Passwortschutz
|
||||
|
||||
Die veröffentlichte Seite ist passwortgeschützt. Geprüft wird **im Server**,
|
||||
nicht im Browser: Ohne gültiges Passwort gibt `server.py` nichts heraus —
|
||||
weder die Seite noch das gebündelte Skript. Ein Passwortschutz allein im
|
||||
Browser wäre wirkungslos, weil das Passwort dann im ausgelieferten Skript
|
||||
stünde und dort mitgelesen werden könnte.
|
||||
|
||||
```bash
|
||||
APP_PASSWORD=dein-passwort python3 server.py
|
||||
```
|
||||
|
||||
- Das Passwort kommt ausschließlich aus der Umgebungsvariable `APP_PASSWORD`
|
||||
(siehe `.env.example`). Es steht **nicht** im Quelltext.
|
||||
- **Fehlt die Variable, startet der Server nicht** und meldet das im Klartext.
|
||||
Das ist Absicht: Ein vergessener Eintrag soll auffallen, statt stillschweigend
|
||||
eine ungeschützte Seite ins Netz zu stellen.
|
||||
- Abgefragt wird per HTTP-Basic-Auth. Der Browser fragt **einmal pro Sitzung**,
|
||||
nicht bei jedem Seitenaufruf — beim Sortieren wäre das sonst unbrauchbar.
|
||||
- Der **Benutzername ist beliebig**; geprüft wird nur das Passwort. Beim
|
||||
Vergleich wird eine zeitkonstante Prüfung verwendet.
|
||||
- `/healthz` antwortet **ohne** Passwort mit `ok`. Das braucht die Überwachung
|
||||
der Hosting-Umgebung, die den geschützten Dienst sonst für ausgefallen hielte.
|
||||
Der Pfad gibt nichts über die Anwendung preis.
|
||||
|
||||
Das Passwort wandert bei einer Basic-Auth-Anmeldung mit jeder Anfrage über die
|
||||
Leitung. Das ist unbedenklich, solange die Seite über HTTPS ausgeliefert wird —
|
||||
worauf du bei der Veröffentlichung achten solltest.
|
||||
|
||||
## Technik
|
||||
|
||||
- Vanilla JavaScript (ES Modules), kein Framework
|
||||
@@ -182,6 +215,8 @@ nicht gesetzt ist).
|
||||
| `src/ui/describe-spec.js` | Gemeinsame Kurzbeschreibung eines Specs (Kapazität, Rank, Geschwindigkeit, Bauform), wahlweise mit Platzhaltern für fehlende Felder; von Treffer-Rückmeldung, „Zuletzt"-Zeile und Sitzungsliste gemeinsam genutzt |
|
||||
| `src/main.js` | Verdrahtung aller Module zur lauffähigen App |
|
||||
| `src/styles.css` | Farbvariablen (Grün/Gelb/Rot der Ampel-Rückmeldung), Layout des Kamera-Vollbilds samt Zielrahmen, Stapel-Leiste und Aktionsknöpfe sowie die Overlays für Treffer-Rückmeldung, Rot-Dialog und Sitzungsliste |
|
||||
| `server.py` | Auslieferung im Betrieb: statischer Server für `dist/` mit Passwortabfrage vor jeder Datei, plus passwortfreier Gesundheitspfad `/healthz`. Nur Python-Standardbibliothek, keine zusätzliche Abhängigkeit |
|
||||
| `.vch/deploy.yaml` | Bau- und Startbefehl sowie Gesundheitspfad für die Hosting-Umgebung |
|
||||
|
||||
`spec`, `pn-decoder`, `ocr-extract`, `session`, `pipeline` und `storage` sind
|
||||
reine Funktionen ohne Browser-Zugriff (kein `window`, `document` oder
|
||||
|
||||
Reference in New Issue
Block a user