/
greenfielder
/
quicknotes
Обзор
Документация
Войти
/
greenfielder
/
quicknotes
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
auth.go
112 строк
3 KB
Dmitry Savenko
mvp version 0.0.1
25 июн 2026, 14:42
25 июн 2026, 14:42
96abad3
Код
Авторство
О чём код?
package main import ( "context" "errors" "net/http" "time" "github.com/golang-jwt/jwt/v5" "golang.org/x/crypto/bcrypt" ) // В проде вынести в переменную окружения! var jwtSecret = []byte("change-me-in-production-please-12345") const ( tokenShort = 24 * time.Hour // без "запомнить" — 1 день tokenLong = 30 * 24 * time.Hour // с "запомнить" — 30 дней cookieName = "token" ) type contextKey string const userCtxKey contextKey = "userID" func hashPassword(pw string) (string, error) { h, err := bcrypt.GenerateFromPassword([]byte(pw), bcrypt.DefaultCost) return string(h), err } func checkPassword(hashed, pw string) bool { return bcrypt.CompareHashAndPassword([]byte(hashed), []byte(pw)) == nil } func generateToken(userID int64, remember bool) (string, time.Duration) { dur := tokenShort if remember { dur = tokenLong } claims := jwt.MapClaims{ "sub": userID, "exp": time.Now().Add(dur).Unix(), } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) s, _ := token.SignedString(jwtSecret) return s, dur } func parseToken(s string) (int64, error) { token, err := jwt.Parse(s, func(t *jwt.Token) (interface{}, error) { if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok { return nil, errors.New("bad signing method") } return jwtSecret, nil }) if err != nil || !token.Valid { return 0, errors.New("invalid token") } claims, ok := token.Claims.(jwt.MapClaims) if !ok { return 0, errors.New("bad claims") } sub, ok := claims["sub"].(float64) if !ok { return 0, errors.New("bad sub") } return int64(sub), nil } func setTokenCookie(w http.ResponseWriter, token string, dur time.Duration) { http.SetCookie(w, &http.Cookie{ Name: cookieName, Value: token, Path: "/", HttpOnly: true, SameSite: http.SameSiteLaxMode, MaxAge: int(dur.Seconds()), }) } func clearTokenCookie(w http.ResponseWriter) { http.SetCookie(w, &http.Cookie{ Name: cookieName, Value: "", Path: "/", HttpOnly: true, MaxAge: -1, }) } func authMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { c, err := r.Cookie(cookieName) if err != nil { http.Error(w, "unauthorized", http.StatusUnauthorized) return } userID, err := parseToken(c.Value) if err != nil { clearTokenCookie(w) http.Error(w, "unauthorized", http.StatusUnauthorized) return } ctx := context.WithValue(r.Context(), userCtxKey, userID) next.ServeHTTP(w, r.WithContext(ctx)) }) } func getUserID(r *http.Request) int64 { v, _ := r.Context().Value(userCtxKey).(int64) return v }