session.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package session
  2. import (
  3. "crypto/sha1"
  4. "encoding/json"
  5. "fmt"
  6. "math/rand"
  7. "net/http"
  8. "os"
  9. "time"
  10. )
  11. type vars struct {
  12. Bool map[string]bool
  13. Int map[string]int
  14. String map[string]string
  15. }
  16. type Session struct {
  17. w http.ResponseWriter
  18. r *http.Request
  19. d string
  20. v *vars
  21. c bool
  22. i string
  23. }
  24. func New(w http.ResponseWriter, r *http.Request, tmpdir string) *Session {
  25. sess := Session{w: w, r: r, d: tmpdir, v: &vars{}, c: false, i: ""}
  26. cookie, err := r.Cookie("session")
  27. if err == nil && len(cookie.Value) == 40 {
  28. // Load from file
  29. sess.i = cookie.Value
  30. fname := sess.d + string(os.PathSeparator) + sess.i
  31. f, err := os.Open(fname)
  32. if err == nil {
  33. defer f.Close()
  34. dec := json.NewDecoder(f)
  35. err = dec.Decode(&sess.v)
  36. if err == nil {
  37. return &sess
  38. }
  39. // Update file last modify time if needs
  40. if info, err := os.Stat(fname); err == nil {
  41. if time.Now().Sub(info.ModTime()) > 30*time.Minute {
  42. _ = os.Chtimes(fname, time.Now(), time.Now())
  43. }
  44. }
  45. }
  46. } else {
  47. // Create new
  48. rand.Seed(time.Now().Unix())
  49. sign := r.RemoteAddr + r.Header.Get("User-Agent") + fmt.Sprintf("%d", int64(time.Now().Unix())) + fmt.Sprintf("%d", int64(rand.Intn(9999999-99)+99))
  50. sess.i = fmt.Sprintf("%x", sha1.Sum([]byte(sign)))
  51. http.SetCookie(w, &http.Cookie{
  52. Name: "session",
  53. Value: sess.i,
  54. Path: "/",
  55. Expires: time.Now().Add(7 * 24 * time.Hour),
  56. HttpOnly: true,
  57. })
  58. }
  59. // Init empty
  60. sess.v = &vars{
  61. Bool: map[string]bool{},
  62. Int: map[string]int{},
  63. String: map[string]string{},
  64. }
  65. return &sess
  66. }
  67. func (this *Session) Close() bool {
  68. if !this.c {
  69. return false
  70. }
  71. r, err := json.Marshal(this.v)
  72. if err == nil {
  73. f, err := os.Create(this.d + string(os.PathSeparator) + this.i)
  74. if err == nil {
  75. defer f.Close()
  76. _, err = f.Write(r)
  77. if err == nil {
  78. this.c = false
  79. return true
  80. }
  81. }
  82. }
  83. return false
  84. }
  85. func (this *Session) Destroy() error {
  86. if this.d == "" || this.i == "" {
  87. return nil
  88. }
  89. err := os.Remove(this.d + string(os.PathSeparator) + this.i)
  90. if err == nil {
  91. this.c = false
  92. }
  93. return err
  94. }