Files
SiteProxy/auth/session.go
2025-12-15 01:13:48 +08:00

95 lines
1.8 KiB
Go

// auth/session.go
package auth
import (
"crypto/rand"
"encoding/hex"
"sync"
"time"
)
type Session struct {
ID string
CreatedAt time.Time
ExpiresAt time.Time
LastSeen time.Time
}
type SessionManager struct {
sessions sync.Map
timeout time.Duration
mu sync.Mutex
}
func NewSessionManager(timeout time.Duration) *SessionManager {
sm := &SessionManager{
timeout: timeout,
}
// 启动清理协程
go sm.cleanup()
return sm
}
func (sm *SessionManager) Create(timeout time.Duration) string {
id := generateSecureToken()
now := time.Now()
sm.sessions.Store(id, &Session{
ID: id,
CreatedAt: now,
ExpiresAt: now.Add(timeout),
LastSeen: now,
})
return id
}
func (sm *SessionManager) Valid(id string) bool {
val, ok := sm.sessions.Load(id)
if !ok {
return false
}
session := val.(*Session)
now := time.Now()
if now.After(session.ExpiresAt) {
sm.sessions.Delete(id)
return false
}
// 更新最后活动时间和过期时间
session.LastSeen = now
session.ExpiresAt = now.Add(sm.timeout)
return true
}
func (sm *SessionManager) Delete(id string) {
sm.sessions.Delete(id)
}
func (sm *SessionManager) cleanup() {
ticker := time.NewTicker(5 * time.Minute)
defer ticker.Stop()
for range ticker.C {
now := time.Now()
sm.sessions.Range(func(key, value interface{}) bool {
session := value.(*Session)
if now.After(session.ExpiresAt) {
sm.sessions.Delete(key)
}
return true
})
}
}
func generateSecureToken() string {
b := make([]byte, 32)
rand.Read(b)
return hex.EncodeToString(b)
}