// 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) }