rework to lighten the main, refactor wrappers. Rehandle csrf and pull config items.

This commit is contained in:
2025-04-15 22:19:55 +01:00
parent 0a5d61ea1e
commit 0a21973237
7 changed files with 142 additions and 11 deletions

View File

@@ -8,14 +8,16 @@ import (
"regexp"
"sort"
"strconv"
"synlotto-website/helpers"
"synlotto-website/middleware"
"synlotto-website/models"
)
func ResultsThunderball(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ip, _, _ := net.SplitHostPort(r.RemoteAddr)
limiter := helpers.GetVisitorLimiter(ip)
limiter := middleware.GetVisitorLimiter(ip)
if !limiter.Allow() {
http.Error(w, "Rate limit exceeded", http.StatusTooManyRequests)

26
handlers/security/csrf.go Normal file
View File

@@ -0,0 +1,26 @@
package security
import (
"fmt"
"net/http"
"github.com/gorilla/csrf"
)
var CSRFMiddleware func(http.Handler) http.Handler
func InitCSRFProtection(csrfKey []byte, isProduction bool) error {
if len(csrfKey) != 32 {
return fmt.Errorf("csrf key must be 32 bytes, got %d", len(csrfKey))
}
CSRFMiddleware = csrf.Protect(
csrfKey,
csrf.Secure(isProduction),
csrf.SameSite(csrf.SameSiteStrictMode),
csrf.Path("/"),
csrf.HttpOnly(true),
)
return nil
}

View File

@@ -0,0 +1,94 @@
package security
import (
"bytes"
"encoding/gob"
"fmt"
"net/http"
"os"
"time"
"github.com/gorilla/securecookie"
"github.com/gorilla/sessions"
)
var (
sessionStore *sessions.CookieStore
sessionName string
authKey []byte
encryptKey []byte
)
func init() {
gob.Register(time.Time{})
}
func LoadSessionKeys(authPath, encryptionPath, name string, isProduction bool) error {
var err error
authKey, err = os.ReadFile(authPath)
if err != nil {
return fmt.Errorf("error loading auth key: %w", err)
}
encryptKey, err = os.ReadFile(encryptionPath)
if err != nil {
return fmt.Errorf("error loading encryption key: %w", err)
}
authKey = bytes.TrimSpace(authKey)
encryptKey = bytes.TrimSpace(encryptKey)
if len(authKey) != 32 || len(encryptKey) != 32 {
return fmt.Errorf("auth and encryption keys must be 32 bytes each")
}
sessionStore = sessions.NewCookieStore(authKey, encryptKey)
sessionStore.Options = &sessions.Options{
Path: "/",
MaxAge: 86400 * 1,
HttpOnly: true,
Secure: isProduction,
SameSite: http.SameSiteLaxMode,
}
sessionName = name
return nil
}
func GetSession(w http.ResponseWriter, r *http.Request) (*sessions.Session, error) {
return sessionStore.Get(r, sessionName)
}
func SecureCookie(w http.ResponseWriter, name, value string, isProduction bool) error {
s := securecookie.New(authKey, encryptKey)
encoded, err := s.Encode(name, value)
if err != nil {
return err
}
http.SetCookie(w, &http.Cookie{
Name: name,
Value: encoded,
Path: "/",
HttpOnly: true,
Secure: isProduction,
SameSite: http.SameSiteStrictMode,
})
return nil
}
func LoadKeyFromFile(path string) ([]byte, error) {
key, err := os.ReadFile(path)
if err != nil {
return nil, err
}
return bytes.TrimSpace(key), nil
}
func ZeroBytes(b []byte) {
for i := range b {
b[i] = 0
}
}