session.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package permit
  2. import (
  3. "context"
  4. "crypto/rand"
  5. "encoding/hex"
  6. "net/http"
  7. "net/url"
  8. "sync"
  9. "time"
  10. "go-common/library/cache/memcache"
  11. "go-common/library/log"
  12. bm "go-common/library/net/http/blademaster"
  13. )
  14. // Session http session.
  15. type Session struct {
  16. Sid string
  17. lock sync.RWMutex
  18. Values map[string]interface{}
  19. }
  20. // SessionConfig config of Session.
  21. type SessionConfig struct {
  22. SessionIDLength int
  23. CookieLifeTime int
  24. CookieName string
  25. Domain string
  26. Memcache *memcache.Config
  27. }
  28. // SessionManager .
  29. type SessionManager struct {
  30. mc *memcache.Pool // Session cache
  31. c *SessionConfig
  32. }
  33. // newSessionManager .
  34. func newSessionManager(c *SessionConfig) (s *SessionManager) {
  35. s = &SessionManager{
  36. mc: memcache.NewPool(c.Memcache),
  37. c: c,
  38. }
  39. return
  40. }
  41. // SessionStart start session.
  42. func (s *SessionManager) SessionStart(ctx *bm.Context) (si *Session) {
  43. // check manager Session id, if err or no exist need new one.
  44. if si, _ = s.cache(ctx); si == nil {
  45. si = s.newSession(ctx)
  46. }
  47. return
  48. }
  49. // SessionRelease flush session into store.
  50. func (s *SessionManager) SessionRelease(ctx *bm.Context, sv *Session) {
  51. // set http cookie
  52. s.setHTTPCookie(ctx, s.c.CookieName, sv.Sid)
  53. // set mc
  54. conn := s.mc.Get(ctx)
  55. defer conn.Close()
  56. key := sv.Sid
  57. item := &memcache.Item{
  58. Key: key,
  59. Object: sv,
  60. Flags: memcache.FlagJSON,
  61. Expiration: int32(s.c.CookieLifeTime),
  62. }
  63. if err := conn.Set(item); err != nil {
  64. log.Error("SessionManager set error(%s,%v)", key, err)
  65. }
  66. }
  67. // SessionDestroy destroy session.
  68. func (s *SessionManager) SessionDestroy(ctx *bm.Context, sv *Session) {
  69. conn := s.mc.Get(ctx)
  70. defer conn.Close()
  71. if err := conn.Delete(sv.Sid); err != nil {
  72. log.Error("SessionManager delete error(%s,%v)", sv.Sid, err)
  73. }
  74. }
  75. func (s *SessionManager) cache(ctx *bm.Context) (res *Session, err error) {
  76. ck, err := ctx.Request.Cookie(s.c.CookieName)
  77. if err != nil || ck == nil {
  78. return
  79. }
  80. sid := ck.Value
  81. // get from cache
  82. conn := s.mc.Get(ctx)
  83. defer conn.Close()
  84. r, err := conn.Get(sid)
  85. if err != nil {
  86. if err == memcache.ErrNotFound {
  87. err = nil
  88. return
  89. }
  90. log.Error("conn.Get(%s) error(%v)", sid, err)
  91. return
  92. }
  93. res = &Session{}
  94. if err = conn.Scan(r, res); err != nil {
  95. log.Error("conn.Scan(%v) error(%v)", string(r.Value), err)
  96. }
  97. return
  98. }
  99. func (s *SessionManager) newSession(ctx context.Context) (res *Session) {
  100. b := make([]byte, s.c.SessionIDLength)
  101. n, err := rand.Read(b)
  102. if n != len(b) || err != nil {
  103. return nil
  104. }
  105. res = &Session{
  106. Sid: hex.EncodeToString(b),
  107. Values: make(map[string]interface{}),
  108. }
  109. return
  110. }
  111. func (s *SessionManager) setHTTPCookie(ctx *bm.Context, name, value string) {
  112. cookie := &http.Cookie{
  113. Name: name,
  114. Value: url.QueryEscape(value),
  115. Path: "/",
  116. HttpOnly: true,
  117. Domain: _defaultDomain,
  118. }
  119. cookie.MaxAge = _defaultCookieLifeTime
  120. cookie.Expires = time.Now().Add(time.Duration(_defaultCookieLifeTime) * time.Second)
  121. http.SetCookie(ctx.Writer, cookie)
  122. }
  123. // Get get value by key.
  124. func (s *Session) Get(key string) (value interface{}) {
  125. s.lock.RLock()
  126. defer s.lock.RUnlock()
  127. value = s.Values[key]
  128. return
  129. }
  130. // Set set value into session.
  131. func (s *Session) Set(key string, value interface{}) (err error) {
  132. s.lock.Lock()
  133. defer s.lock.Unlock()
  134. s.Values[key] = value
  135. return
  136. }