1
0
mirror of https://github.com/astaxie/beego.git synced 2024-11-25 19:10:54 +00:00

add comments for session packages, part 1

This commit is contained in:
傅小黑 2014-01-29 01:05:56 +08:00
parent ab8f8d532a
commit 0e2872324f
3 changed files with 75 additions and 9 deletions

View File

@ -11,12 +11,15 @@ import (
var cookiepder = &CookieProvider{} var cookiepder = &CookieProvider{}
// Cookie SessionStore
type CookieSessionStore struct { type CookieSessionStore struct {
sid string sid string
values map[interface{}]interface{} //session data values map[interface{}]interface{} // session data
lock sync.RWMutex 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 { func (st *CookieSessionStore) Set(key, value interface{}) error {
st.lock.Lock() st.lock.Lock()
defer st.lock.Unlock() defer st.lock.Unlock()
@ -24,6 +27,7 @@ func (st *CookieSessionStore) Set(key, value interface{}) error {
return nil return nil
} }
// Get value from cookie session
func (st *CookieSessionStore) Get(key interface{}) interface{} { func (st *CookieSessionStore) Get(key interface{}) interface{} {
st.lock.RLock() st.lock.RLock()
defer st.lock.RUnlock() defer st.lock.RUnlock()
@ -35,6 +39,7 @@ func (st *CookieSessionStore) Get(key interface{}) interface{} {
return nil return nil
} }
// Delete value in cookie session
func (st *CookieSessionStore) Delete(key interface{}) error { func (st *CookieSessionStore) Delete(key interface{}) error {
st.lock.Lock() st.lock.Lock()
defer st.lock.Unlock() defer st.lock.Unlock()
@ -42,6 +47,7 @@ func (st *CookieSessionStore) Delete(key interface{}) error {
return nil return nil
} }
// Clean all values in cookie session
func (st *CookieSessionStore) Flush() error { func (st *CookieSessionStore) Flush() error {
st.lock.Lock() st.lock.Lock()
defer st.lock.Unlock() defer st.lock.Unlock()
@ -49,10 +55,12 @@ func (st *CookieSessionStore) Flush() error {
return nil return nil
} }
// Return id of this cookie session
func (st *CookieSessionStore) SessionID() string { func (st *CookieSessionStore) SessionID() string {
return st.sid return st.sid
} }
// Write cookie session to http response cookie
func (st *CookieSessionStore) SessionRelease(w http.ResponseWriter) { func (st *CookieSessionStore) SessionRelease(w http.ResponseWriter) {
str, err := encodeCookie(cookiepder.block, str, err := encodeCookie(cookiepder.block,
cookiepder.config.SecurityKey, cookiepder.config.SecurityKey,
@ -79,12 +87,21 @@ type cookieConfig struct {
Maxage int `json:"maxage"` Maxage int `json:"maxage"`
} }
// Cookie session provider
type CookieProvider struct { type CookieProvider struct {
maxlifetime int64 maxlifetime int64
config *cookieConfig config *cookieConfig
block cipher.Block 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 { func (pder *CookieProvider) SessionInit(maxlifetime int64, config string) error {
pder.config = &cookieConfig{} pder.config = &cookieConfig{}
err := json.Unmarshal([]byte(config), pder.config) err := json.Unmarshal([]byte(config), pder.config)
@ -104,6 +121,8 @@ func (pder *CookieProvider) SessionInit(maxlifetime int64, config string) error
return nil 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) { func (pder *CookieProvider) SessionRead(sid string) (SessionStore, error) {
maps, _ := decodeCookie(pder.block, maps, _ := decodeCookie(pder.block,
pder.config.SecurityKey, pder.config.SecurityKey,
@ -116,26 +135,32 @@ func (pder *CookieProvider) SessionRead(sid string) (SessionStore, error) {
return rs, nil return rs, nil
} }
// Cookie session is always existed
func (pder *CookieProvider) SessionExist(sid string) bool { func (pder *CookieProvider) SessionExist(sid string) bool {
return true return true
} }
// Implement method, no used.
func (pder *CookieProvider) SessionRegenerate(oldsid, sid string) (SessionStore, error) { func (pder *CookieProvider) SessionRegenerate(oldsid, sid string) (SessionStore, error) {
return nil, nil return nil, nil
} }
// Implement method, no used.
func (pder *CookieProvider) SessionDestroy(sid string) error { func (pder *CookieProvider) SessionDestroy(sid string) error {
return nil return nil
} }
// Implement method, no used.
func (pder *CookieProvider) SessionGC() { func (pder *CookieProvider) SessionGC() {
return return
} }
// Implement method, return 0.
func (pder *CookieProvider) SessionAll() int { func (pder *CookieProvider) SessionAll() int {
return 0 return 0
} }
// Implement method, no used.
func (pder *CookieProvider) SessionUpdate(sid string) error { func (pder *CookieProvider) SessionUpdate(sid string) error {
return nil return nil
} }

View File

@ -18,6 +18,7 @@ var (
gcmaxlifetime int64 gcmaxlifetime int64
) )
// File session store
type FileSessionStore struct { type FileSessionStore struct {
f *os.File f *os.File
sid string sid string
@ -25,6 +26,7 @@ type FileSessionStore struct {
values map[interface{}]interface{} values map[interface{}]interface{}
} }
// Set value to file session
func (fs *FileSessionStore) Set(key, value interface{}) error { func (fs *FileSessionStore) Set(key, value interface{}) error {
fs.lock.Lock() fs.lock.Lock()
defer fs.lock.Unlock() defer fs.lock.Unlock()
@ -32,6 +34,7 @@ func (fs *FileSessionStore) Set(key, value interface{}) error {
return nil return nil
} }
// Get value from file session
func (fs *FileSessionStore) Get(key interface{}) interface{} { func (fs *FileSessionStore) Get(key interface{}) interface{} {
fs.lock.RLock() fs.lock.RLock()
defer fs.lock.RUnlock() defer fs.lock.RUnlock()
@ -43,6 +46,7 @@ func (fs *FileSessionStore) Get(key interface{}) interface{} {
return nil return nil
} }
// Delete value in file session by given key
func (fs *FileSessionStore) Delete(key interface{}) error { func (fs *FileSessionStore) Delete(key interface{}) error {
fs.lock.Lock() fs.lock.Lock()
defer fs.lock.Unlock() defer fs.lock.Unlock()
@ -50,6 +54,7 @@ func (fs *FileSessionStore) Delete(key interface{}) error {
return nil return nil
} }
// Clean all values in file session
func (fs *FileSessionStore) Flush() error { func (fs *FileSessionStore) Flush() error {
fs.lock.Lock() fs.lock.Lock()
defer fs.lock.Unlock() defer fs.lock.Unlock()
@ -57,10 +62,12 @@ func (fs *FileSessionStore) Flush() error {
return nil return nil
} }
// Get file session store id
func (fs *FileSessionStore) SessionID() string { func (fs *FileSessionStore) SessionID() string {
return fs.sid return fs.sid
} }
// Write file session to local file with Gob string
func (fs *FileSessionStore) SessionRelease(w http.ResponseWriter) { func (fs *FileSessionStore) SessionRelease(w http.ResponseWriter) {
defer fs.f.Close() defer fs.f.Close()
b, err := encodeGob(fs.values) b, err := encodeGob(fs.values)
@ -72,17 +79,23 @@ func (fs *FileSessionStore) SessionRelease(w http.ResponseWriter) {
fs.f.Write(b) fs.f.Write(b)
} }
// File session provider
type FileProvider struct { type FileProvider struct {
maxlifetime int64 maxlifetime int64
savePath string savePath string
} }
// Init file session provider.
// savePath sets the session files path.
func (fp *FileProvider) SessionInit(maxlifetime int64, savePath string) error { func (fp *FileProvider) SessionInit(maxlifetime int64, savePath string) error {
fp.maxlifetime = maxlifetime fp.maxlifetime = maxlifetime
fp.savePath = savePath fp.savePath = savePath
return nil 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) { func (fp *FileProvider) SessionRead(sid string) (SessionStore, error) {
err := os.MkdirAll(path.Join(fp.savePath, string(sid[0]), string(sid[1])), 0777) err := os.MkdirAll(path.Join(fp.savePath, string(sid[0]), string(sid[1])), 0777)
if err != nil { if err != nil {
@ -117,6 +130,8 @@ func (fp *FileProvider) SessionRead(sid string) (SessionStore, error) {
return ss, nil return ss, nil
} }
// Check file session exist.
// it checkes the file named from sid exist or not.
func (fp *FileProvider) SessionExist(sid string) bool { func (fp *FileProvider) SessionExist(sid string) bool {
_, err := os.Stat(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid)) _, err := os.Stat(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid))
if err == nil { 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 { func (fp *FileProvider) SessionDestroy(sid string) error {
os.Remove(path.Join(fp.savePath)) os.Remove(path.Join(fp.savePath))
return nil return nil
} }
// Recycle files in save path
func (fp *FileProvider) SessionGC() { func (fp *FileProvider) SessionGC() {
gcmaxlifetime = fp.maxlifetime gcmaxlifetime = fp.maxlifetime
filepath.Walk(fp.savePath, gcpath) filepath.Walk(fp.savePath, gcpath)
} }
// Get active file session number.
// it walks save path to count files.
func (fp *FileProvider) SessionAll() int { func (fp *FileProvider) SessionAll() int {
a := &activeSession{} a := &activeSession{}
err := filepath.Walk(fp.savePath, func(path string, f os.FileInfo, err error) error { 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 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) { func (fp *FileProvider) SessionRegenerate(oldsid, sid string) (SessionStore, error) {
err := os.MkdirAll(path.Join(fp.savePath, string(oldsid[0]), string(oldsid[1])), 0777) err := os.MkdirAll(path.Join(fp.savePath, string(oldsid[0]), string(oldsid[1])), 0777)
if err != nil { if err != nil {
@ -197,6 +218,7 @@ func (fp *FileProvider) SessionRegenerate(oldsid, sid string) (SessionStore, err
return ss, nil return ss, nil
} }
// remove file in save path if expired
func gcpath(path string, info os.FileInfo, err error) error { func gcpath(path string, info os.FileInfo, err error) error {
if err != nil { if err != nil {
return err return err

View File

@ -14,6 +14,7 @@ import (
"time" "time"
) )
// SessionStore contains all data for one session process with specific id.
type SessionStore interface { type SessionStore interface {
Set(key, value interface{}) error //set session value Set(key, value interface{}) error //set session value
Get(key interface{}) interface{} //get session value Get(key interface{}) interface{} //get session value
@ -23,6 +24,8 @@ type SessionStore interface {
Flush() error //delete all data Flush() error //delete all data
} }
// Provider contains global session methods and saved SessionStores.
// it can operate a SessionStore by its id.
type Provider interface { type Provider interface {
SessionInit(gclifetime int64, config string) error SessionInit(gclifetime int64, config string) error
SessionRead(sid string) (SessionStore, error) SessionRead(sid string) (SessionStore, error)
@ -61,16 +64,24 @@ type managerConfig struct {
ProviderConfig string `json:"providerConfig"` ProviderConfig string `json:"providerConfig"`
} }
// Manager contains Provider and its configuration.
type Manager struct { type Manager struct {
provider Provider provider Provider
config *managerConfig config *managerConfig
} }
//options // Create new Manager with provider name and json config string.
//1. is https default false // provider name:
//2. hashfunc default sha1 // 1. cookie
//3. hashkey default beegosessionkey // 2. file
//4. maxage default is none // 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) { func NewManager(provideName, config string) (*Manager, error) {
provider, ok := provides[provideName] provider, ok := provides[provideName]
if !ok { if !ok {
@ -102,7 +113,8 @@ func NewManager(provideName, config string) (*Manager, error) {
}, nil }, 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) { func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (session SessionStore) {
cookie, err := r.Cookie(manager.config.CookieName) cookie, err := r.Cookie(manager.config.CookieName)
if err != nil || cookie.Value == "" { if err != nil || cookie.Value == "" {
@ -144,7 +156,7 @@ func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (se
return return
} }
//Destroy sessionid // Destroy session by its id in http request cookie.
func (manager *Manager) SessionDestroy(w http.ResponseWriter, r *http.Request) { func (manager *Manager) SessionDestroy(w http.ResponseWriter, r *http.Request) {
cookie, err := r.Cookie(manager.config.CookieName) cookie, err := r.Cookie(manager.config.CookieName)
if err != nil || cookie.Value == "" { 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) { func (manager *Manager) GetProvider(sid string) (sessions SessionStore, err error) {
sessions, err = manager.provider.SessionRead(sid) sessions, err = manager.provider.SessionRead(sid)
return return
} }
// Start session gc process.
// it can do gc in times after gc lifetime.
func (manager *Manager) GC() { func (manager *Manager) GC() {
manager.provider.SessionGC() manager.provider.SessionGC()
time.AfterFunc(time.Duration(manager.config.Gclifetime)*time.Second, func() { manager.GC() }) 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) { func (manager *Manager) SessionRegenerateId(w http.ResponseWriter, r *http.Request) (session SessionStore) {
sid := manager.sessionId(r) sid := manager.sessionId(r)
cookie, err := r.Cookie(manager.config.CookieName) cookie, err := r.Cookie(manager.config.CookieName)
@ -198,20 +214,23 @@ func (manager *Manager) SessionRegenerateId(w http.ResponseWriter, r *http.Reque
return return
} }
// Get all active sessions count number.
func (manager *Manager) GetActiveSession() int { func (manager *Manager) GetActiveSession() int {
return manager.provider.SessionAll() return manager.provider.SessionAll()
} }
// Set hash function for generating session id.
func (manager *Manager) SetHashFunc(hasfunc, hashkey string) { func (manager *Manager) SetHashFunc(hasfunc, hashkey string) {
manager.config.SessionIDHashFunc = hasfunc manager.config.SessionIDHashFunc = hasfunc
manager.config.SessionIDHashKey = hashkey manager.config.SessionIDHashKey = hashkey
} }
// Set cookie with https.
func (manager *Manager) SetSecure(secure bool) { func (manager *Manager) SetSecure(secure bool) {
manager.config.Secure = secure 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) { func (manager *Manager) sessionId(r *http.Request) (sid string) {
bs := make([]byte, 24) bs := make([]byte, 24)
if _, err := io.ReadFull(rand.Reader, bs); err != nil { if _, err := io.ReadFull(rand.Reader, bs); err != nil {