Manager的主体
package sessionimport ( "fmt" "log" "net/http" "net/url" "sync" "time")type Manager struct { cookieName string lock sync.Mutex provider Provider maxlifetime int64}var ( provides map[string]Provider = make(map[string]Provider))func RegisterProvider(name string, provider Provider) { if nil == provider { panic("session: Register provider is nil") } if _, dup := provides[name]; dup { panic("session: Register called twice for provider " + name) } provides[name] = provider}func NewManager(providerName string, cookieName string, maxlifetime int64) (*Manager, error) { provider, ok := provides[providerName] if !ok { return nil, fmt.Errorf("sessions: unknown provider %q (forgotten import?)", providerName) } return &Manager{ provider: provider, cookieName: cookieName, maxlifetime: maxlifetime, }, nil}var doStartGC sync.Oncefunc (manager *Manager) DoStartGC() { doStartGC.Do(func() { manager.doGC() })}func (manager *Manager) doGC() { manager.lock.Lock() defer manager.lock.Unlock() log.Println("manager gc ...") manager.provider.SessionGC(manager.maxlifetime) log.Println("manager gc done") time.AfterFunc(time.Duration(manager.maxlifetime)*time.Millisecond, func() { manager.doGC() })}func (manager *Manager) SessionStart(writer http.ResponseWriter, req *http.Request) (session Session) { manager.lock.Lock() defer manager.lock.Unlock() cookie, err := req.Cookie(manager.cookieName) if err != nil || cookie.Value == "" { sid := makeSessionId() session, _ = manager.provider.SessionInit(sid) http.SetCookie( writer, &http.Cookie{ Name: manager.cookieName, Value: url.QueryEscape(sid), Path: "/", HttpOnly: true, MaxAge: int(manager.maxlifetime), }, ) return } sid, _ := url.QueryUnescape(cookie.Value) session, _ = manager.provider.SessionRead(sid) return}func (manager *Manager) SessionDestroy(writer http.ResponseWriter, req *http.Request) { cookie, err := req.Cookie(manager.cookieName) if err != nil || cookie.Value == "" { return } manager.lock.Lock() defer manager.lock.Unlock() manager.provider.SessionDestroy(cookie.Value) http.SetCookie( writer, &http.Cookie{ Name: manager.cookieName, Path: "/", HttpOnly: true, Expires: time.Now(), MaxAge: -1, }, )}
类别定义
package sessiontype Provider interface { SessionInit(sid string) (Session, error) SessionRead(sid string) (Session, error) SessionDestroy(sid string) error SessionGC(maxlifetime int64)}type Session interface { Set(key, value interface{}) error Get(key interface{}) interface{} Delete(key interface{}) error GetString(key SessionID() string}
以及生成sessionid的方式:
package sessionimport ( "crypto/rand" "encoding/base64" "io" "log")func makeSessionId() string { b := make([]byte, 32) if _, err := io.ReadFull(rand.Reader, b); err != nil { log.Println("abnormal rand read for generating session-id") return "" } return base64.URLEncoding.EncodeToString(b)}
参考文章:
https://astaxie.gitbooks.io/build-web-application-with-golang/content/en/06.1.html