Prisijungimas, atsijungimas, apsaugotas skydelis
Dabar viską atgaivink. Penki failai kaip skirtukai, priklausomybių tvarka: dashboard.templ → auth.templ → auth.go → handlers.go → router.go (apsaugotas puslapis, prisijungimo forma, apdorotojai, tada sujungimas). Keturi — nauji arba pakeisti nuo 4 pamokos.
1. internal/web/dashboard.templ (naujas) — tik nariams skirtas puslapis. Kol kas jis tik pasveikina nav.Email; dokumentų fazė jį užpildo.
2. internal/web/auth.templ (modify) — Register gauna nav parametrą, ir prisijungia Login šablonas (el. paštas + slaptažodis, viena bendra klaidos vieta).
3. internal/handlers/auth.go (modify) — pamokos širdis:
func (h *Handlers) nav(r *http.Request) web.Nav { /* UserFrom → {LoggedIn, Email} */ }
func (h *Handlers) Login(w, r) {
user, err := h.Queries.GetUserByEmail(...) // nežinomas el. paštas → invalid()
if !auth.CheckPassword(user.PasswordHash, pw) { invalid(); return } // blogas slaptažodis → invalid()
h.Sessions.Create(r.Context(), w, user.ID) // tas pats kvietimas kaip registracijoje
http.Redirect(w, r, "/dashboard", http.StatusSeeOther)
}
func (h *Handlers) Logout(w, r) {
h.Sessions.Destroy(r.Context(), w, r) // ← tas vienas DELETE
http.Redirect(w, r, "/", http.StatusSeeOther)
}
nav() naujas; Register dabar perduoda h.nav(r) ir nukreipia į /dashboard; Dashboard atvaizduoja apsaugotą puslapį. invalid() — ta viena bendra klaida.
4. internal/handlers/handlers.go (modify) — Home gauna vieną šaką: prisijungęs lankytojas nukreipiamas į /dashboard, o ne mato viešą puslapį.
5. internal/handlers/router.go (modify) — trys pakeitimai: r.Use(h.LoadUser) (anotuoja kiekvieną užklausą), login/logout maršrutai ir autentifikuota grupė:
r.Group(func(pr chi.Router) {
pr.Use(h.RequireAuth)
pr.Get("/dashboard", h.Dashboard)
})
Patikrink. templ generate && go run ./cmd/signflow, tada:
-
Apsaugotas maršrutas, atsijungus. Aplankyk
http://localhost:8080/dashboard→ būsi nublokštas į/login.RequireAuthveikia. -
Prisijunk. Naudok paskyrą iš 4 pamokos. Atsidursi skydelyje, o antraštė dabar rodo tavo el. paštą ir Log out mygtuką —
LoadUserišsprendė slapuką,navatvaizdavo būseną. -
Atsijunk. Paspausk. Grįžti į viešą pradinį puslapį, antraštė rodo Log in / Register. Ir serveryje:
$ psql signflow -c "SELECT count(*) FROM sessions;" count ------- 0 ← eilutės nebėra. Tai atšaukimas, kurio JWT negali. -
Bendra klaida.
/loginbandyk blogą slaptažodį, tada neegzistuojantį el. paštą. Abu sako „Invalid email or password." — vienodai, tad nė vienas neatskleidžia, ar paskyra egzistuoja.
Spąstai (nukreipimas po POST). Pastebėk: prisijungimas/atsijungimas/registracija visi baigiasi
http.StatusSeeOther(303) nukreipimais, niekada neatvaizduojant tiesiai per POST. Tai POST/redirect/GET šablonas: naršyklės perkrovimas iš naujo užklausia skydelio (GET), o ne pakartotinai pateikia prisijungimo formą. Be jo „perkrauti" pakartotų POST — klasikinė dvigubo pateikimo klaida.