Login: Sitzungsdauer wählbar (1 Stunde bis 1 Jahr)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TiXsPUqw7oeomZ8wZrQW5q
This commit is contained in:
irrlicht
2026-09-27 00:04:07 +02:00
co-authored by Claude Opus 5.5
parent 9cac33d167
commit 9a7282ed1d
3 changed files with 13 additions and 4 deletions
+3 -2
View File
@@ -96,9 +96,10 @@ func handleLogin(w http.ResponseWriter, r *http.Request) error {
func startSession(w http.ResponseWriter, r *http.Request, uid int64) error { func startSession(w http.ResponseWriter, r *http.Request, uid int64) error {
now := time.Now().Unix() now := time.Now().Unix()
// timeout ist clientgesteuert -> serverseitig deckeln, damit niemand eine // timeout ist clientgesteuert -> serverseitig deckeln, damit niemand eine
// quasi-unbegrenzte Session anlegen kann. Default 1 Tag, Maximum 30 Tage. // quasi-unbegrenzte Session anlegen kann. Default 1 Tag, Maximum 1 Jahr
// (größte Option im Login-Formular).
timeoutSec, _ := strconv.ParseInt(r.FormValue("timeout"), 10, 64) timeoutSec, _ := strconv.ParseInt(r.FormValue("timeout"), 10, 64)
const maxTimeout = 30 * 86400 const maxTimeout = 365 * 86400
if timeoutSec <= 0 { if timeoutSec <= 0 {
timeoutSec = 86400 timeoutSec = 86400
} }
+9 -1
View File
@@ -53,7 +53,15 @@ export function AuthBox() {
<h2>Login</h2>{" "} <h2>Login</h2>{" "}
<input name="user" placeholder="Nutzername" autoComplete="username" />{" "} <input name="user" placeholder="Nutzername" autoComplete="username" />{" "}
<input name="pass" type="password" placeholder="Passwort" autoComplete="current-password" />{" "} <input name="pass" type="password" placeholder="Passwort" autoComplete="current-password" />{" "}
<input name="timeout" type="hidden" value="86400" />{" "} <label>
Angemeldet bleiben für{" "}
<select name="timeout" defaultValue="86400">
<option value="3600">1 Stunde</option>
<option value="86400">1 Tag</option>
<option value="604800">1 Woche</option>
<option value="31536000">1 Jahr</option>
</select>
</label>{" "}
<button type="submit" disabled={busy}>Einloggen</button>{" "} <button type="submit" disabled={busy}>Einloggen</button>{" "}
<p className="muted">Noch kein Konto? <a href="#" onClick={show("register")}>Registrieren</a></p> <p className="muted">Noch kein Konto? <a href="#" onClick={show("register")}>Registrieren</a></p>
</form> </form>
+1 -1
View File
@@ -50,7 +50,7 @@ Endpunkte antworten ohne gültige Session mit `401 auth.required`.
| Methode | Pfad | Auth | Request | Erfolg | | Methode | Pfad | Auth | Request | Erfolg |
|---------|------|------|---------|--------| |---------|------|------|---------|--------|
| POST | `/api/auth/login` | – | `user`, `pass`, `timeout` (s, Default 1 Tag, max. 30 Tage) | `200 {"status":"ok"}` + Cookie; bereits angemeldet: `200 {"status":"already_logged_in"}` | | POST | `/api/auth/login` | – | `user`, `pass`, `timeout` (s, Default 1 Tag, max. 1 Jahr) | `200 {"status":"ok"}` + Cookie; bereits angemeldet: `200 {"status":"already_logged_in"}` |
| POST | `/api/auth/newuser` | – | `user` (3–32 Zeichen), `pass1` (min. 10), `pass2` | `201 {"username"}` | | POST | `/api/auth/newuser` | – | `user` (3–32 Zeichen), `pass1` (min. 10), `pass2` | `201 {"username"}` |
| POST | `/api/auth/logout` | – | – | `200 {"status":"ok"}`, löscht Cookie | | POST | `/api/auth/logout` | – | – | `200 {"status":"ok"}`, löscht Cookie |
| GET | `/api/auth/sessioninfo` | ✓ | – | `200 {"uid","created_at","expires","description"}`, ohne Session `401` | | GET | `/api/auth/sessioninfo` | ✓ | – | `200 {"uid","created_at","expires","description"}`, ohne Session `401` |