Files
nms_cxy/lib/session/session.go

169 lines
3.9 KiB
Go

package session
import (
"crypto/rand"
"encoding/base64"
"fmt"
"io"
"net/http"
"strconv"
"strings"
"sync"
"time"
"be.ems/lib/log"
"be.ems/lib/oauth"
"be.ems/restagent/config"
)
// SessionMgr session manager
type SessManager struct {
name string
expires int64
lock sync.RWMutex
sessions map[string]*Session
}
// Session
type Session struct {
token string
time time.Time
permission []bool
values map[interface{}]interface{}
}
// NewSessionMgr create session manager
func NewSessManager(name string) *SessManager {
smgr := &SessManager{name: name, expires: (int64)(config.GetExpiresFromConfig()), sessions: make(map[string]*Session)}
go smgr.SessionGC()
return smgr
}
// NewSession create session
func (smgr *SessManager) NewSession(w http.ResponseWriter, r *http.Request, plist []bool) string {
smgr.lock.Lock()
defer smgr.lock.Unlock()
token := oauth.GenRandToken("omc") // Generate new token to session ID
session := &Session{token: token, time: time.Now(), permission: plist, values: make(map[interface{}]interface{})}
smgr.sessions[token] = session
return token
}
// EndSession
func (smgr *SessManager) EndSession(w http.ResponseWriter, r *http.Request) {
token := smgr.GetTokenFromHttpRequest(r)
smgr.lock.Lock()
defer smgr.lock.Unlock()
delete(smgr.sessions, token)
}
// Handshake session, restart session
func (smgr *SessManager) ShakeSession(token string) bool {
smgr.lock.Lock()
defer smgr.lock.Unlock()
for _, s := range smgr.sessions {
if token == s.token {
log.Debug("session time:", s.time)
s.time = time.Now()
return true
}
}
return false
}
// EndSessionByID end the session by session ID
func (smgr *SessManager) DeleteSession(token string) {
smgr.lock.Lock()
defer smgr.lock.Unlock()
delete(smgr.sessions, token)
}
// SetSessionValue set value fo session
func (smgr *SessManager) SetSessionValue(token string, key interface{}, value interface{}) error {
smgr.lock.Lock()
defer smgr.lock.Unlock()
if session, ok := smgr.sessions[token]; ok {
session.values[key] = value
return nil
}
return fmt.Errorf("invalid session ID")
}
// GetSessionValue get value fo session
func (smgr *SessManager) GetSessionValue(token string, key interface{}) (interface{}, error) {
smgr.lock.RLock()
defer smgr.lock.RUnlock()
if session, ok := smgr.sessions[token]; ok {
if val, ok := session.values[key]; ok {
return val, nil
}
}
return nil, fmt.Errorf("invalid session ID")
}
func (smgr *SessManager) GetTokenFromHttpRequest(r *http.Request) string {
for k, v := range r.Header {
if strings.ToLower(k) == "accesstoken" && len(v) != 0 {
log.Debug("AccessToken:", v[0])
return v[0]
}
}
return ""
}
// IsValidToken check token is valid or not
func (smgr *SessManager) IsValidToken(token string) bool {
smgr.lock.Lock()
defer smgr.lock.Unlock()
if _, ok := smgr.sessions[token]; ok {
return true
}
return false
}
// IsCarriedToken check token is carried
func (smgr *SessManager) IsCarriedToken(r *http.Request) (string, bool) {
token := smgr.GetTokenFromHttpRequest(r)
if token == "" {
return "", false
}
return token, true
}
// GetPermissionFromSession get permission from session by token
func (smgr *SessManager) GetPermissionFromSession(token string) []bool {
if s, ok := smgr.sessions[token]; ok {
return s.permission
}
return nil
}
// SessionGC maintain session
func (smgr *SessManager) SessionGC() {
smgr.lock.Lock()
defer smgr.lock.Unlock()
for token, session := range smgr.sessions {
if session.time.Unix()+smgr.expires < time.Now().Unix() {
delete(smgr.sessions, token)
}
}
time.AfterFunc(time.Duration(smgr.expires)*time.Second, func() { smgr.SessionGC() })
}
// NewSessionID generate unique ID
func (smgr *SessManager) NewSessionID() string {
b := make([]byte, 32)
if _, err := io.ReadFull(rand.Reader, b); err != nil {
nano := time.Now().UnixNano()
return strconv.FormatInt(nano, 10)
}
return base64.URLEncoding.EncodeToString(b)
}