Golang的session管理器

對於一些須要對用戶進行管理(好比驗證操做的權限等)的站點來講,session管理器是必不可少的。下面實現了一個線程安全的簡單session管理類。
生產環境:golang1.4.2+win7x64
golang1.4.2+centos6.5×64html

1.代碼以下:golang

 

package Helper import ( "crypto/rand"
    "encoding/base64"
    "io"
    "net/http"
    "net/url"
    "strconv"
    "sync"
    "time" ) /*Session會話管理*/ type SessionMgr struct { mCookieName string       //客戶端cookie名稱
    mLock        sync.RWMutex //互斥(保證線程安全)
    mMaxLifeTime int64        //垃圾回收時間
 mSessions map[string]*Session //保存session的指針[sessionID] = session
} //建立會話管理器(cookieName:在瀏覽器中cookie的名字;maxLifeTime:最長生命週期)
func NewSessionMgr(cookieName string, maxLifeTime int64) *SessionMgr { mgr := &SessionMgr{mCookieName: cookieName, mMaxLifeTime: maxLifeTime, mSessions: make(map[string]*Session)} //啓動定時回收
 go mgr.GC() return mgr } //在開始頁面登錄頁面,開始Session
func (mgr *SessionMgr) StartSession(w http.ResponseWriter, r *http.Request) string { mgr.mLock.Lock() defer mgr.mLock.Unlock() //不管原來有沒有,都從新建立一個新的session
    newSessionID := url.QueryEscape(mgr.NewSessionID()) //存指針
    var session *Session = &Session{mSessionID: newSessionID, mLastTimeAccessed: time.Now(), mValues: make(map[interface{}]interface{})} mgr.mSessions[newSessionID] = session //讓瀏覽器cookie設置過時時間
    cookie := http.Cookie{Name: mgr.mCookieName, Value: newSessionID, Path: "/", HttpOnly: true, MaxAge: int(mgr.mMaxLifeTime)} http.SetCookie(w, &cookie) return newSessionID } //結束Session
func (mgr *SessionMgr) EndSession(w http.ResponseWriter, r *http.Request) { cookie, err := r.Cookie(mgr.mCookieName) if err != nil || cookie.Value == "" { return } else { mgr.mLock.Lock() defer mgr.mLock.Unlock() delete(mgr.mSessions, cookie.Value) //讓瀏覽器cookie馬上過時
        expiration := time.Now() cookie := http.Cookie{Name: mgr.mCookieName, Path: "/", HttpOnly: true, Expires: expiration, MaxAge: -1} http.SetCookie(w, &cookie) } } //結束session
func (mgr *SessionMgr) EndSessionBy(sessionID string) { mgr.mLock.Lock() defer mgr.mLock.Unlock() delete(mgr.mSessions, sessionID) } //設置session裏面的值
func (mgr *SessionMgr) SetSessionVal(sessionID string, key interface{}, value interface{}) { mgr.mLock.Lock() defer mgr.mLock.Unlock() if session, ok := mgr.mSessions[sessionID]; ok { session.mValues[key] = value } } //獲得session裏面的值
func (mgr *SessionMgr) GetSessionVal(sessionID string, key interface{}) (interface{}, bool) { mgr.mLock.RLock() defer mgr.mLock.RUnlock() if session, ok := mgr.mSessions[sessionID]; ok { if val, ok := session.mValues[key]; ok { return val, ok } } return nil, false } //獲得sessionID列表
func (mgr *SessionMgr) GetSessionIDList() []string { mgr.mLock.RLock() defer mgr.mLock.RUnlock() sessionIDList := make([]string, 0) for k, _ := range mgr.mSessions { sessionIDList = append(sessionIDList, k) } return sessionIDList[0:len(sessionIDList)] } //判斷Cookie的合法性(每進入一個頁面都須要判斷合法性)
func (mgr *SessionMgr) CheckCookieValid(w http.ResponseWriter, r *http.Request) string { var cookie, err = r.Cookie(mgr.mCookieName) if cookie == nil || err != nil { return "" } mgr.mLock.Lock() defer mgr.mLock.Unlock() sessionID := cookie.Value if session, ok := mgr.mSessions[sessionID]; ok { session.mLastTimeAccessed = time.Now() //判斷合法性的同時,更新最後的訪問時間
        return sessionID } return "" } //更新最後訪問時間
func (mgr *SessionMgr) GetLastAccessTime(sessionID string) time.Time { mgr.mLock.RLock() defer mgr.mLock.RUnlock() if session, ok := mgr.mSessions[sessionID]; ok { return session.mLastTimeAccessed } return time.Now() } //GC回收
func (mgr *SessionMgr) GC() { mgr.mLock.Lock() defer mgr.mLock.Unlock() for sessionID, session := range mgr.mSessions { //刪除超過期限的session
        if session.mLastTimeAccessed.Unix()+mgr.mMaxLifeTime < time.Now().Unix() { delete(mgr.mSessions, sessionID) } } //定時回收
    time.AfterFunc(time.Duration(mgr.mMaxLifeTime)*time.Second, func() { mgr.GC() }) } //建立惟一ID
func (mgr *SessionMgr) 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) } //—————————————————————————— /*會話*/ type Session struct { mSessionID string                      //惟一id
    mLastTimeAccessed time.Time                   //最後訪問時間
    mValues           map[interface{}]interface{} //其它對應值(保存用戶所對應的一些值,好比用戶權限之類)
}

 

 

 

2.使用方法
①定義一個全局變量web

1 var sessionMgr *Helper.SessionMgr = nil //session管理器

 

②在程序入口處,建立一個session的對象數據庫

1 //建立session管理器,」TestCookieName」是瀏覽器中cookie的名字,3600是瀏覽器cookie的有效時間(秒) 
2 sessionMgr = Helper.NewSessionMgr("TestCookieName", 3600)

 

③在用戶登陸時進行登陸用戶合法性判斷並設置屬性centos

 1 //處理登陸 
 2 func login(w http.ResponseWriter, r *http.Request) {  3     if r.Method == "GET" {  4         t, _ := template.ParseFiles("web/MgrSvr_login.html")  5  t.Execute(w, nil)  6   
 7     } else if r.Method == "POST" {  8         //請求的是登錄數據,那麼執行登錄的邏輯判斷 
 9  r.ParseForm() 10   
11         //可使用template.HTMLEscapeString()來避免用戶進行js注入 
12         username := r.FormValue("username") 13         password := r.FormValue("password") 14   
15         //在數據庫中獲得對應數據 
16         var userID int = 0  
17   
18         userRow := db.QueryRow(loginUserQuery, username, password) 19         userRow.Scan(&amp;userID) 20   
21         //TODO:判斷用戶名和密碼 
22         if userID != 0 { 23             //建立客戶端對應cookie以及在服務器中進行記錄 
24             var sessionID = sessionMgr.StartSession(w, r) 25   
26             var loginUserInfo = UserInfo{ID: userID, UserName: username, Password: password, Alias: alias, 27  Desc: desc, ChannelAuth: channel_authority, IsSuperAdmin: is_super_admin, IsNewClientAuth: is_newclient_authority, 28  IsPayAuth: is_pay_authority, IsItemsAuth: is_itmes_authority, IsRealtimeAuth: is_realtime_authority, 29  IsPayCodeAuth: is_paycode_authority, IsUserAuth: is_user_authority, IsBgOpAuth: is_bgop_authority, IsHZRaidenNMMWeak: is_hz_raidenn_mmweak, 30  IsManualDataMgr: is_manual_data_mgr, IsManualDataQuery: is_manual_data_query} 31   
32             //踢除重複登陸的 
33             var onlineSessionIDList = sessionMgr.GetSessionIDList() 34   
35             for _, onlineSessionID := range onlineSessionIDList { 36                 if userInfo, ok := sessionMgr.GetSessionVal(onlineSessionID, "UserInfo"); ok { 37                     if value, ok := userInfo.(UserInfo); ok { 38                         if value.ID == userID { 39  sessionMgr.EndSessionBy(onlineSessionID) 40  } 41  } 42  } 43  } 44   
45             //設置變量值 
46  sessionMgr.SetSessionVal(sessionID, "UserInfo", loginUserInfo) 47   
48             //TODO 設置其它數據 49   
50             //TODO 轉向成功頁面 
51   
52             return  
53  } 54  } 55 }

 

③在用戶退出時刪除對應session瀏覽器

1 //處理退出 
2 func logout(w http.ResponseWriter, r *http.Request) { 3     sessionMgr.EndSession(w, r) //用戶退出時刪除對應session 
4     http.Redirect(w, r, "/login", http.StatusFound) 5     return  
6 }

 

④在每一個頁面中進行用戶合法性驗證安全

1 func test_session_valid(w http.ResponseWriter, r *http.Request) { 2     var sessionID = sessionMgr.CheckCookieValid(w, r) 3   
4     if sessionID == "" { 5         http.Redirect(w, r, "/login", http.StatusFound) 6         return  
7  } 8 }
相關文章
相關標籤/搜索