【リアライズ】golangセッションセッションgolangシングルユーザーログイン認証に使用される、維持

著作権:https://blog.csdn.net/qq_21852449/article/details/88093941

変数の前の多くは、現在のバージョンでは、ユーザーはシングルサインオンを可能にし、簡単なセッション管理のメモリ版に属し、少し年上のジュニアパートナーが私を許して得た、時間を追加して、単一着陸制限のログインケースでマルチユーザー、ブラウザを実装する方法についての話の神を持っていると思ってい。

package hsession

import (
	"crypto/rand"
	"encoding/base64"
	"io"
	"net/http"
	"net/url"
	"strconv"
	"sync"
	"time"
)

// manage all sessions in system running
type HSessionMgr struct {
	hCookieName  string               // client cookie name
	hMaxLifeTime int64                // determine whether to delete
	hSessions    map[string]*HSession // container for sessions
	hLock        sync.RWMutex         // mutex
}

type HSession struct {
	hSessionID        string //unique key
	hLastTimeAccessed time.Time
	hValues           map[interface{}]interface{} //store variables
}

// create  a session manager
// run GC
func NewSessionMgr(cookieName string, maxLifeTime int64) *HSessionMgr {
	mgr := &HSessionMgr{hCookieName: cookieName, hMaxLifeTime: maxLifeTime, hSessions: make(map[string]*HSession)}
	go mgr.GC()
	return mgr
}

//func NewSessionMgr(cookieName string,  args []interface{}) *HSessionMgr {
//	maxLifeTime :=3600
//	mgr := &HSessionMgr{hCookieName: cookieName, hMaxLifeTime: maxLifeTime, hSessions: make(map[string]*HSession)}
//	go mgr.GC()
//	return mgr
//}

//start session  at login action
func (hSessionMgr *HSessionMgr) StartSession(w http.ResponseWriter, r *http.Request) string {
	hSessionMgr.hLock.Lock()                                    // add lock
	defer hSessionMgr.hLock.Unlock()                            // auto unlock
	newSessionID := url.QueryEscape(hSessionMgr.NewSessionID()) //create new session,whether or not
	sessionPoint := &HSession{hSessionID: newSessionID, hLastTimeAccessed: time.Now(), hValues: make(map[interface{}]interface{})}
	hSessionMgr.hSessions[newSessionID] = sessionPoint
	//set cookie
	responseCookie := http.Cookie{Name: hSessionMgr.hCookieName, Value: newSessionID, Path: "/", HttpOnly: true, MaxAge: int(hSessionMgr.hMaxLifeTime)}
	http.SetCookie(w, &responseCookie) // write
	return newSessionID
}

//stop session 1.drop session object from memory 2.set expire cookie for web
func (hSessionMgr *HSessionMgr) StopSession(w http.ResponseWriter, r *http.Request) {
	cookie, err := r.Cookie(hSessionMgr.hCookieName)
	if err != nil || cookie.Value == "" { //no cookie value
		return
	} else { //have cookie value
		hSessionMgr.hLock.Lock()
		defer hSessionMgr.hLock.Unlock()
		delete(hSessionMgr.hSessions, cookie.Value) //drop session's point in  session' map
		// set cookie timeout right now
		expireTime := time.Now()
		cookie := http.Cookie{Name: hSessionMgr.hCookieName, Path: "/", HttpOnly: true, Expires: expireTime, MaxAge: -1}
		http.SetCookie(w, &cookie)
	}
}

//manually stopping the session
func (hSessionMgr *HSessionMgr) StopSessionBySessionID(sessionID string) {
	hSessionMgr.hLock.Lock()
	defer hSessionMgr.hLock.Unlock()
	delete(hSessionMgr.hSessions, sessionID)
}

// set values in  the session
func (hSessionMgr *HSessionMgr) SetSessionInnerData(sessionID string, key interface{}, value interface{}) {
	hSessionMgr.hLock.Lock()
	defer hSessionMgr.hLock.Unlock()
	if session, ok := hSessionMgr.hSessions[sessionID]; ok {
		session.hValues[key] = value
	}
}

// get values in the session
func (hSessionMgr *HSessionMgr) GetSessionInnerData(sessionID string, key interface{}) (interface{}, bool) {
	hSessionMgr.hLock.Lock()
	defer hSessionMgr.hLock.Unlock()
	if session, ok := hSessionMgr.hSessions[sessionID]; ok {
		if val, ok := session.hValues[key]; ok {
			return val, ok
		}
	}
	return nil, false
}

// get sessionID list
func (hSessionMgr HSessionMgr) GetSessionIDList() []string {
	hSessionMgr.hLock.Lock()
	defer hSessionMgr.hLock.Unlock()
	sessionIDList := make([]string, 0)
	for key, _ := range hSessionMgr.hSessions {
		sessionIDList = append(sessionIDList, key)
	}
	return sessionIDList[0:len(sessionIDList)] //len cap
}

//validate cookie using in intercept when get request from client
func (hSessionMgr *HSessionMgr) CheckValidAndFlashTime(w http.ResponseWriter, r *http.Request) (string, bool) {
	cookie, err := r.Cookie(hSessionMgr.hCookieName)
	if cookie == nil || err != nil {
		return "cookie is nil", false
	}
	hSessionMgr.hLock.Lock()
	defer hSessionMgr.hLock.Unlock()
	currentSessionID := cookie.Value
	if session, ok := hSessionMgr.hSessions[currentSessionID]; ok { //judge if existed
		session.hLastTimeAccessed = time.Now() //flash time
		return currentSessionID, true
	}
	return "no session id in memory", false
}

// get last flash time
func (hSessionMgr *HSessionMgr) GetLastAccessedTime(sessionID string) (time.Time, bool) {
	hSessionMgr.hLock.Lock()
	defer hSessionMgr.hLock.Unlock()
	if session, ok := hSessionMgr.hSessions[sessionID]; ok {
		return session.hLastTimeAccessed, true
	}
	return time.Now(), false
}

func (hSessionMgr *HSessionMgr) GC() {
	hSessionMgr.hLock.Lock()
	defer hSessionMgr.hLock.Unlock()
	for sessionID, session := range hSessionMgr.hSessions {
		if session.hLastTimeAccessed.Unix()+hSessionMgr.hMaxLifeTime < time.Now().Unix() {
			//uid := strconv.FormatInt(session.hValues["uid"].(int64), 10)  todo 更新用户状态为离线
			delete(hSessionMgr.hSessions, sessionID)
		}
	}
	time.AfterFunc(time.Duration(hSessionMgr.hMaxLifeTime)*time.Second, func() {
		hSessionMgr.GC()
	})
}

// create unique key
func (hSessionMgr *HSessionMgr) 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)
}

func (hSessionMgr *HSessionMgr) CurrentUserID(r *http.Request) int64 {
	//user := model.User{}
	cookie, err := r.Cookie(hSessionMgr.hCookieName)
	if cookie == nil || err != nil {
		return -1
	}
	session := hSessionMgr.hSessions[cookie.Value]
	//service.User.Get(r,uid,&user)
	uid := session.hValues["uid"].(int64)
	return uid

}

func (hSessionMgr *HSessionMgr) DropByUserID(uid int64) bool {
	for key, session := range hSessionMgr.hSessions {
		if session.hValues["uid"] == uid {
			delete(hSessionMgr.hSessions, key)
			return true
		}
	}
	return false
}

var HSessionHelper *HSessionMgr //singleton pattern

おすすめ

転載: blog.csdn.net/qq_21852449/article/details/88093941