Hotfix - Login-Bug
Some checks failed
release-tag / release-image (push) Has been cancelled

This commit is contained in:
2025-07-31 23:12:11 +02:00
parent 41cee8af1d
commit 842c541c13
3 changed files with 143 additions and 23 deletions

133
main.go
View File

@@ -1,7 +1,9 @@
package main
import (
"crypto/rand"
"database/sql"
"encoding/hex"
"encoding/json"
"fmt"
"html/template"
@@ -15,6 +17,7 @@ import (
"sync"
"time"
"golang.org/x/crypto/bcrypt"
_ "modernc.org/sqlite" // statt github.com/mattn/go-sqlite3
)
@@ -37,14 +40,15 @@ func Enabled(k string, def bool) bool {
}
var (
username = GetENV("KT_USERNAME", "root")
password = GetENV("KT_PASSWORD", "root")
membername = GetENV("KT_MEMBER", "demo")
productive = Enabled("KT_PRODUCTIVE", false)
hasimpressum = Enabled("KT_HASIMPRESSUM", false)
impressum = GetENV("KT_IMPRESSUM", "")
orte = []string{}
schiffe = []string{
username = GetENV("KT_USERNAME", "root")
password = GetENV("KT_PASSWORD", "root")
membername = GetENV("KT_MEMBER", "demo")
productive = Enabled("KT_PRODUCTIVE", false)
hasimpressum = Enabled("KT_HASIMPRESSUM", false)
impressum = GetENV("KT_IMPRESSUM", "")
hashedPassword = ""
orte = []string{}
schiffe = []string{
"", "100i", "125a", "135c", "Arrow", "Aurora CL", "Aurora ES", "Aurora LN", "Aurora LX", "Aurora MR",
"Avenger Stalker", "Avenger Titan", "Avenger Titan Renegade", "Avenger Warlock",
"Blade", "Buccaneer", "C1 Spirit", "C2 Hercules Starlifter", "M2 Hercules Starlifter", "A2 Hercules Starlifter", "C8 Pisces", "C8R Pisces Rescue",
@@ -190,7 +194,40 @@ func reverse(s string) string {
func isAuthenticated(r *http.Request) bool {
cookie, err := r.Cookie("session")
return err == nil && cookie.Value == "authenticated"
if err != nil {
fmt.Println("Debug-1:", err)
return false
}
// Prüfen, ob der Token im sessionStore existiert
a, ok := sessionStore[cookie.Value]
fmt.Println(ok, a)
fmt.Println(sessionStore)
return ok
}
var sessionStore = make(map[string]string) // token → username
var loginAttempts = make(map[string]int)
var loginLastAttempt = make(map[string]time.Time)
var loginBlockedUntil = make(map[string]time.Time)
var loginMutex sync.Mutex
func hashPassword(pw string) string {
hash, _ := bcrypt.GenerateFromPassword([]byte(pw), bcrypt.DefaultCost)
return string(hash)
}
func checkPasswordHash(pw, hash string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(pw))
return err == nil
}
func generateSessionToken() string {
b := make([]byte, 32)
_, err := rand.Read(b)
if err != nil {
return "" // handle error besser im echten Code
}
return hex.EncodeToString(b)
}
func main() {
@@ -220,6 +257,8 @@ func main() {
}
}
hashedPassword = hashPassword(password)
var pois []POI
if err := json.Unmarshal(data, &pois); err != nil {
panic(err)
@@ -246,34 +285,88 @@ func main() {
}
http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
ip := strings.Split(r.RemoteAddr, ":")[0]
loginMutex.Lock()
blockUntil, blocked := loginBlockedUntil[ip]
if blocked && time.Now().Before(blockUntil) {
loginMutex.Unlock()
http.Error(w, "Zu viele Fehlversuche. Bitte versuch es später erneut.", http.StatusTooManyRequests)
return
}
loginMutex.Unlock()
if r.Method == http.MethodPost {
r.ParseForm()
user := r.FormValue("username")
pass := r.FormValue("password")
if user == username && pass == password {
if user == username && checkPasswordHash(pass, hashedPassword) {
token := generateSessionToken()
// Speichere Session
sessionStore[token] = user
fmt.Println("Login", token)
// Cookie setzen
http.SetCookie(w, &http.Cookie{
Name: "session",
Value: "authenticated",
Path: "/",
Name: "session",
Value: token,
Path: "/",
HttpOnly: true,
Secure: true,
SameSite: http.SameSiteLaxMode,
})
// Erfolgreich -> Versuche zurücksetzen
loginMutex.Lock()
delete(loginAttempts, ip)
delete(loginLastAttempt, ip)
delete(loginBlockedUntil, ip)
loginMutex.Unlock()
http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
// Fehlversuch behandeln
loginMutex.Lock()
loginAttempts[ip]++
loginLastAttempt[ip] = time.Now()
if loginAttempts[ip] >= 5 {
loginBlockedUntil[ip] = time.Now().Add(10 * time.Minute)
}
loginMutex.Unlock()
http.Error(w, "Login fehlgeschlagen", http.StatusUnauthorized)
return
}
// GET: Login-Formular
w.Header().Set("Content-Type", "text/html")
w.Write([]byte(loginForm))
})
http.HandleFunc("/logout", func(w http.ResponseWriter, r *http.Request) {
http.SetCookie(w, &http.Cookie{
Name: "session",
Value: "",
Path: "/",
MaxAge: -1,
})
cookie, err := r.Cookie("session")
if err == nil {
token := cookie.Value
fmt.Println("Logout", token)
// Token aus dem serverseitigen Store löschen
delete(sessionStore, token)
// Cookie ungültig machen
http.SetCookie(w, &http.Cookie{
Name: "session",
Value: "",
Path: "/",
MaxAge: -1,
HttpOnly: true,
Secure: true,
SameSite: http.SameSiteLaxMode,
})
}
http.Redirect(w, r, "/", http.StatusSeeOther)
})
@@ -387,6 +480,7 @@ func main() {
cacheMutex.RUnlock()
if validCache {
cachedData.LoggedIn = isAuthenticated(r)
tmpl.Execute(w, cachedData)
return
}
@@ -529,7 +623,6 @@ func main() {
OffeneSumme: offeneSumme,
Abteilungen: abteilungen,
Monatsstatistik: monatsStat,
LoggedIn: isAuthenticated(r),
Member: membername,
HasImpressum: hasimpressum,
Impressum: impressum,