diff --git a/session/sess_cookie.go b/session/sess_cookie.go index 7962be18..ddf1a902 100644 --- a/session/sess_cookie.go +++ b/session/sess_cookie.go @@ -11,12 +11,15 @@ import ( var cookiepder = &CookieProvider{} +// Cookie SessionStore type CookieSessionStore struct { sid string - values map[interface{}]interface{} //session data + values map[interface{}]interface{} // session data lock sync.RWMutex } +// Set value to cookie session. +// the value are encoded as gob with hash block string. func (st *CookieSessionStore) Set(key, value interface{}) error { st.lock.Lock() defer st.lock.Unlock() @@ -24,6 +27,7 @@ func (st *CookieSessionStore) Set(key, value interface{}) error { return nil } +// Get value from cookie session func (st *CookieSessionStore) Get(key interface{}) interface{} { st.lock.RLock() defer st.lock.RUnlock() @@ -35,6 +39,7 @@ func (st *CookieSessionStore) Get(key interface{}) interface{} { return nil } +// Delete value in cookie session func (st *CookieSessionStore) Delete(key interface{}) error { st.lock.Lock() defer st.lock.Unlock() @@ -42,6 +47,7 @@ func (st *CookieSessionStore) Delete(key interface{}) error { return nil } +// Clean all values in cookie session func (st *CookieSessionStore) Flush() error { st.lock.Lock() defer st.lock.Unlock() @@ -49,10 +55,12 @@ func (st *CookieSessionStore) Flush() error { return nil } +// Return id of this cookie session func (st *CookieSessionStore) SessionID() string { return st.sid } +// Write cookie session to http response cookie func (st *CookieSessionStore) SessionRelease(w http.ResponseWriter) { str, err := encodeCookie(cookiepder.block, cookiepder.config.SecurityKey, @@ -79,12 +87,21 @@ type cookieConfig struct { Maxage int `json:"maxage"` } +// Cookie session provider type CookieProvider struct { maxlifetime int64 config *cookieConfig block cipher.Block } +// Init cookie session provider with max lifetime and config json. +// maxlifetime is ignored. +// json config: +// securityKey - hash string +// blockKey - gob encode hash string. it's saved as aes crypto. +// securityName - recognized name in encoded cookie string +// cookieName - cookie name +// maxage - cookie max life time. func (pder *CookieProvider) SessionInit(maxlifetime int64, config string) error { pder.config = &cookieConfig{} err := json.Unmarshal([]byte(config), pder.config) @@ -104,6 +121,8 @@ func (pder *CookieProvider) SessionInit(maxlifetime int64, config string) error return nil } +// Get SessionStore in cooke. +// decode cooke string to map and put into SessionStore with sid. func (pder *CookieProvider) SessionRead(sid string) (SessionStore, error) { maps, _ := decodeCookie(pder.block, pder.config.SecurityKey, @@ -116,26 +135,32 @@ func (pder *CookieProvider) SessionRead(sid string) (SessionStore, error) { return rs, nil } +// Cookie session is always existed func (pder *CookieProvider) SessionExist(sid string) bool { return true } +// Implement method, no used. func (pder *CookieProvider) SessionRegenerate(oldsid, sid string) (SessionStore, error) { return nil, nil } +// Implement method, no used. func (pder *CookieProvider) SessionDestroy(sid string) error { return nil } +// Implement method, no used. func (pder *CookieProvider) SessionGC() { return } +// Implement method, return 0. func (pder *CookieProvider) SessionAll() int { return 0 } +// Implement method, no used. func (pder *CookieProvider) SessionUpdate(sid string) error { return nil } diff --git a/session/sess_file.go b/session/sess_file.go index 5d33d0e2..73eec874 100644 --- a/session/sess_file.go +++ b/session/sess_file.go @@ -18,6 +18,7 @@ var ( gcmaxlifetime int64 ) +// File session store type FileSessionStore struct { f *os.File sid string @@ -25,6 +26,7 @@ type FileSessionStore struct { values map[interface{}]interface{} } +// Set value to file session func (fs *FileSessionStore) Set(key, value interface{}) error { fs.lock.Lock() defer fs.lock.Unlock() @@ -32,6 +34,7 @@ func (fs *FileSessionStore) Set(key, value interface{}) error { return nil } +// Get value from file session func (fs *FileSessionStore) Get(key interface{}) interface{} { fs.lock.RLock() defer fs.lock.RUnlock() @@ -43,6 +46,7 @@ func (fs *FileSessionStore) Get(key interface{}) interface{} { return nil } +// Delete value in file session by given key func (fs *FileSessionStore) Delete(key interface{}) error { fs.lock.Lock() defer fs.lock.Unlock() @@ -50,6 +54,7 @@ func (fs *FileSessionStore) Delete(key interface{}) error { return nil } +// Clean all values in file session func (fs *FileSessionStore) Flush() error { fs.lock.Lock() defer fs.lock.Unlock() @@ -57,10 +62,12 @@ func (fs *FileSessionStore) Flush() error { return nil } +// Get file session store id func (fs *FileSessionStore) SessionID() string { return fs.sid } +// Write file session to local file with Gob string func (fs *FileSessionStore) SessionRelease(w http.ResponseWriter) { defer fs.f.Close() b, err := encodeGob(fs.values) @@ -72,17 +79,23 @@ func (fs *FileSessionStore) SessionRelease(w http.ResponseWriter) { fs.f.Write(b) } +// File session provider type FileProvider struct { maxlifetime int64 savePath string } +// Init file session provider. +// savePath sets the session files path. func (fp *FileProvider) SessionInit(maxlifetime int64, savePath string) error { fp.maxlifetime = maxlifetime fp.savePath = savePath return nil } +// Read file session by sid. +// if file is not exist, create it. +// the file path is generated from sid string. func (fp *FileProvider) SessionRead(sid string) (SessionStore, error) { err := os.MkdirAll(path.Join(fp.savePath, string(sid[0]), string(sid[1])), 0777) if err != nil { @@ -117,6 +130,8 @@ func (fp *FileProvider) SessionRead(sid string) (SessionStore, error) { return ss, nil } +// Check file session exist. +// it checkes the file named from sid exist or not. func (fp *FileProvider) SessionExist(sid string) bool { _, err := os.Stat(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid)) if err == nil { @@ -126,16 +141,20 @@ func (fp *FileProvider) SessionExist(sid string) bool { } } +// Remove all files in this save path func (fp *FileProvider) SessionDestroy(sid string) error { os.Remove(path.Join(fp.savePath)) return nil } +// Recycle files in save path func (fp *FileProvider) SessionGC() { gcmaxlifetime = fp.maxlifetime filepath.Walk(fp.savePath, gcpath) } +// Get active file session number. +// it walks save path to count files. func (fp *FileProvider) SessionAll() int { a := &activeSession{} err := filepath.Walk(fp.savePath, func(path string, f os.FileInfo, err error) error { @@ -148,6 +167,8 @@ func (fp *FileProvider) SessionAll() int { return a.total } +// Generate new sid for file session. +// it delete old file and create new file named from new sid. func (fp *FileProvider) SessionRegenerate(oldsid, sid string) (SessionStore, error) { err := os.MkdirAll(path.Join(fp.savePath, string(oldsid[0]), string(oldsid[1])), 0777) if err != nil { @@ -197,6 +218,7 @@ func (fp *FileProvider) SessionRegenerate(oldsid, sid string) (SessionStore, err return ss, nil } +// remove file in save path if expired func gcpath(path string, info os.FileInfo, err error) error { if err != nil { return err diff --git a/session/session.go b/session/session.go index f41ba85b..d1a44538 100644 --- a/session/session.go +++ b/session/session.go @@ -14,6 +14,7 @@ import ( "time" ) +// SessionStore contains all data for one session process with specific id. type SessionStore interface { Set(key, value interface{}) error //set session value Get(key interface{}) interface{} //get session value @@ -23,6 +24,8 @@ type SessionStore interface { Flush() error //delete all data } +// Provider contains global session methods and saved SessionStores. +// it can operate a SessionStore by its id. type Provider interface { SessionInit(gclifetime int64, config string) error SessionRead(sid string) (SessionStore, error) @@ -61,16 +64,24 @@ type managerConfig struct { ProviderConfig string `json:"providerConfig"` } +// Manager contains Provider and its configuration. type Manager struct { provider Provider config *managerConfig } -//options -//1. is https default false -//2. hashfunc default sha1 -//3. hashkey default beegosessionkey -//4. maxage default is none +// Create new Manager with provider name and json config string. +// provider name: +// 1. cookie +// 2. file +// 3. memory +// 4. redis +// 5. mysql +// json config: +// 1. is https default false +// 2. hashfunc default sha1 +// 3. hashkey default beegosessionkey +// 4. maxage default is none func NewManager(provideName, config string) (*Manager, error) { provider, ok := provides[provideName] if !ok { @@ -102,7 +113,8 @@ func NewManager(provideName, config string) (*Manager, error) { }, nil } -//get Session +// Start session. generate or read the session id from http request. +// if session id exists, return SessionStore with this id. func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (session SessionStore) { cookie, err := r.Cookie(manager.config.CookieName) if err != nil || cookie.Value == "" { @@ -144,7 +156,7 @@ func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (se return } -//Destroy sessionid +// Destroy session by its id in http request cookie. func (manager *Manager) SessionDestroy(w http.ResponseWriter, r *http.Request) { cookie, err := r.Cookie(manager.config.CookieName) if err != nil || cookie.Value == "" { @@ -161,16 +173,20 @@ func (manager *Manager) SessionDestroy(w http.ResponseWriter, r *http.Request) { } } +// Get SessionStore by its id. func (manager *Manager) GetProvider(sid string) (sessions SessionStore, err error) { sessions, err = manager.provider.SessionRead(sid) return } +// Start session gc process. +// it can do gc in times after gc lifetime. func (manager *Manager) GC() { manager.provider.SessionGC() time.AfterFunc(time.Duration(manager.config.Gclifetime)*time.Second, func() { manager.GC() }) } +// Regenerate a session id for this SessionStore who's id is saving in http request. func (manager *Manager) SessionRegenerateId(w http.ResponseWriter, r *http.Request) (session SessionStore) { sid := manager.sessionId(r) cookie, err := r.Cookie(manager.config.CookieName) @@ -198,20 +214,23 @@ func (manager *Manager) SessionRegenerateId(w http.ResponseWriter, r *http.Reque return } +// Get all active sessions count number. func (manager *Manager) GetActiveSession() int { return manager.provider.SessionAll() } +// Set hash function for generating session id. func (manager *Manager) SetHashFunc(hasfunc, hashkey string) { manager.config.SessionIDHashFunc = hasfunc manager.config.SessionIDHashKey = hashkey } +// Set cookie with https. func (manager *Manager) SetSecure(secure bool) { manager.config.Secure = secure } -//remote_addr cruunixnano randdata +// generate session id with rand string, unix nano time, remote addr by hash function. func (manager *Manager) sessionId(r *http.Request) (sid string) { bs := make([]byte, 24) if _, err := io.ReadFull(rand.Reader, bs); err != nil {