Tema
/
Interneto svetainių serverio dalies kūrimas GO

Registracija nuo pradžios iki galo

Dabar registracija nuo pradžios iki galo. Šeši failai kaip skirtukai, priklausomybių tvarka: auth.templutil.gohandlers.goauth.gorouter.gomain.go (forma, pagalbininkas, struktūra, kuri gauna sesijų valdytoją, apdorotojas, maršrutai, sujungimas). Trys — pakeitimai; diff'ai perkelia 1–3 pamokas.

1. internal/web/auth.templ (naujas) — Register forma. Paprasti HTML laukai su minlength/maxlength, atitinkančiais 8–64 taisyklę. (Kol kas jokio CSRF lauko — 6 pamoka.)

2. internal/handlers/util.go (naujas) — vienas pagalbininkas, isUniqueViolation, atpažįstantis Postgres klaidą 23505 (unique-constraint), tad dublikato el. pašto lenktynės tampa draugišku pranešimu, o ne 500.

3. internal/handlers/handlers.go (modify) — Handlers struktūra gauna Sessions *session.Manager lauką, New jį ima, ir atsiranda mažas serverError pagalbininkas (užloguoja tikrą klaidą, grąžina bendrą 500). Home ir Health nepakito.

4. internal/handlers/auth.go (naujas) — RegisterForm (atvaizduoja formą) ir Register, kuris yra visas srautas:

if !validEmail(emailAddr) { fail("Please enter a valid email address."); return }
if password != confirm    { fail("Passwords do not match."); return }
hash, err := auth.HashPassword(password)   // bcrypt; ErrPasswordLength → draugiškas pranešimas
// dublikato patikra (gražus pranešimas) + CreateUser (lenktynes tvarko isUniqueViolation)
h.Sessions.Create(r.Context(), w, user.ID) // ← išduoda sesiją + nustato slapuką
http.Redirect(w, r, "/", http.StatusSeeOther)

Nukreipimas kol kas veda į / — skydelis prisijungusiems yra 5 pamokos darbas.

5. internal/handlers/router.go (modify) — du maršrutai: GET /register (forma) ir POST /register (apdorotojas).

6. cmd/signflow/main.go (modify) — sukurk valdytoją ir paduok jį:

sessions := session.NewManager(queries, cfg.IsProd())
h := handlers.New(cfg, queries, sessions, log)

Patikrink. Sugeneruok ir paleisk:

sqlc generate && templ generate
go run ./cmd/signflow

Atsidaryk http://localhost:8080/register, sukurk paskyrą (pvz. you@example.com / slaptažodis 8–64 simboliai). Būsi nukreiptas namo, o vartotojų skaičius paauga. Dabar apžiūrėk, kas nutiko:

$ psql signflow -c "SELECT email, left(password_hash, 7) AS hash_prefix FROM users;"
      email       | hash_prefix
------------------+-------------
 you@example.com  | $2a$12$          ← bcrypt, cost 12 ($2a$12$…)

$ psql signflow -c "SELECT left(token_hash, 12) AS stored, expires_at > now() AS live FROM sessions;"
    stored    | live
--------------+------
 3f9a1c2e...  | t             ← SHA-256 MAIŠA, ne slapuko žetonas

O pats slapukas neša savo vėliavas:

$ curl -si -c /dev/null -X POST localhost:8080/register \
    -d 'email=x@y.co&password=password123&confirm=password123' | grep -i set-cookie
Set-Cookie: signflow_session=Xa9...; Path=/; Expires=...; HttpOnly; SameSite=Lax

HttpOnly ir SameSite=Lax yra; Secure nėra, nes esam ant http dev aplinkoje (produkcijoje jis atsiranda). Slapuko žetonas nėra duomenų bazėje saugoma reikšmė — DB turi tik jo SHA-256.

Spąstai (bcrypt 72 baitų skardis). Pabandyk registruotis su 100 simbolių slaptažodžiu: gausi „Password must be between 8 and 64 characters." — atmesta mūsų ribos, prieš tai, kai bcrypt tyliai ignoruotų viską po 72-o baito. Be ribos, du skirtingi ilgi slaptažodžiai, sutampantys pirmais 72 baitais, būtų sukeičiami prisijungiant. Tvora svarbi.