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:
parent
ab8f8d532a
commit
0e2872324f
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user