web_session.go 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. package main
  2. import (
  3. "crypto/rand"
  4. "encoding/hex"
  5. "net/http"
  6. "sync"
  7. "time"
  8. )
  9. type sessionInfo struct {
  10. last time.Time
  11. }
  12. var (
  13. sessionMu sync.Mutex
  14. sessions = make(map[string]*sessionInfo)
  15. )
  16. const (
  17. idleTimeout = 5 * time.Minute
  18. gcPeriod = 1 * time.Hour
  19. )
  20. func createSession() string {
  21. buf := make([]byte, 32)
  22. rand.Read(buf)
  23. return hex.EncodeToString(buf)
  24. }
  25. func addSession(id string) {
  26. sessionMu.Lock()
  27. sessions[id] = &sessionInfo{last: time.Now()}
  28. sessionMu.Unlock()
  29. }
  30. func hasSession(id string) bool {
  31. now := time.Now()
  32. sessionMu.Lock()
  33. defer sessionMu.Unlock()
  34. s, ok := sessions[id]
  35. if !ok {
  36. return false
  37. }
  38. if now.Sub(s.last) > idleTimeout {
  39. delete(sessions, id)
  40. return false
  41. }
  42. s.last = now
  43. return true
  44. }
  45. func checkSession(r *http.Request) bool {
  46. c, err := r.Cookie("session_id")
  47. if err != nil {
  48. return false
  49. }
  50. return hasSession(c.Value)
  51. }
  52. func startSessionCleaner() {
  53. go func() {
  54. ticker := time.NewTicker(gcPeriod)
  55. defer ticker.Stop()
  56. for range ticker.C {
  57. now := time.Now()
  58. sessionMu.Lock()
  59. for k, s := range sessions {
  60. if now.Sub(s.last) > idleTimeout {
  61. delete(sessions, k)
  62. }
  63. }
  64. sessionMu.Unlock()
  65. }
  66. }()
  67. }