对于一些需要对用户进行管理(比如验证操作的权限等)的站点来说,session管理器是必不可少的。下面实现了一个线程安全的简单session管理类。
生产环境:golang1.4.2+win7x64
golang1.4.2+centos6.5×64
1.代码如下:
1 package Helper 2 3 import ( 4 “crypto/rand” 5 “encoding/base64″ 6 “io” 7 “net/http” 8 “net/url” 9 “strconv” 10 “sync” 11 “time” 12 ) 13 14 /*Session会话管理*/ 15 type SessionMgr struct { 16 mCookieName string //客户端cookie名称 17 mLock sync.RWMutex //互斥(保证线程安全) 18 mMaxLifeTime int64 //垃圾回收时间 19 20 mSessions map[string]*Session //保存session的指针[sessionID] = session 21 } 22 23 //创建会话管理器(cookieName:在浏览器中cookie的名字;maxLifeTime:最长生命周期) 24 func NewSessionMgr(cookieName string, maxLifeTime int64) *SessionMgr { 25 mgr := &SessionMgr{mCookieName: cookieName, mMaxLifeTime: maxLifeTime, mSessions: make(map[string]*Session)} 26 27 //启动定时回收 28 go mgr.GC() 29 30 return mgr 31 } 32 33 //在开始页面登陆页面,开始Session 34 func (mgr *SessionMgr) StartSession(w http.ResponseWriter, r *http.Request) string { 35 mgr.mLock.Lock() 36 defer mgr.mLock.Unlock() 37 38 //无论原来有没有,都重新创建一个新的session 39 newSessionID := url.QueryEscape(mgr.NewSessionID()) 40 41 //存指针 42 var session *Session = &Session{mSessionID: newSessionID, mLastTimeAccessed: time.Now(), mValues: make(map[interface{}]interface{})} 43 mgr.mSessions[newSessionID] = session 44 //让浏览器cookie设置过期时间 45 cookie := http.Cookie{Name: mgr.mCookieName, Value: newSessionID, Path: “/”, HttpOnly: true, MaxAge: int(mgr.mMaxLifeTime)} 46 http.SetCookie(w, &cookie) 47 48 return newSessionID 49 } 50 51 //结束Session 52 func (mgr *SessionMgr) EndSession(w http.ResponseWriter, r *http.Request) { 53 cookie, err := r.Cookie(mgr.mCookieName) 54 if err != nil || cookie.Value == “” { 55 return 56 } else { 57 mgr.mLock.Lock() 58 defer mgr.mLock.Unlock() 59 60 delete(mgr.mSessions, cookie.Value) 61 62 //让浏览器cookie立刻过期 63 expiration := time.Now() 64 cookie := http.Cookie{Name: mgr.mCookieName, Path: “/”, HttpOnly: true, Expires: expiration, MaxAge: -1} 65 http.SetCookie(w, &cookie) 66 } 67 } 68 69 //结束session 70 func (mgr *SessionMgr) EndSessionBy(sessionID string) { 71 mgr.mLock.Lock() 72 defer mgr.mLock.Unlock() 73 74 delete(mgr.mSessions, sessionID) 75 } 76 77 //设置session里面的值 78 func (mgr *SessionMgr) SetSessionVal(sessionID string, key interface{}, value interface{}) { 79 mgr.mLock.Lock() 80 defer mgr.mLock.Unlock() 81 82 if session, ok := mgr.mSessions[sessionID]; ok { 83 session.mValues[key] = value 84 } 85 } 86 87 //得到session里面的值 88 func (mgr *SessionMgr) GetSessionVal(sessionID string, key interface{}) (interface{}, bool) { 89 mgr.mLock.RLock() 90 defer mgr.mLock.RUnlock() 91 92 if session, ok := mgr.mSessions[sessionID]; ok { 93 if val, ok := session.mValues[key]; ok { 94 return val, ok 95 } 96 } 97 98 return nil, false 99 } 100 101 //得到sessionID列表 102 func (mgr *SessionMgr) GetSessionIDList() []string { 103 mgr.mLock.RLock() 104 defer mgr.mLock.RUnlock() 105 106 sessionIDList := make([]string, 0) 107 108 for k, _ := range mgr.mSessions { 109 sessionIDList = append(sessionIDList, k) 110 } 111 112 return sessionIDList[0:len(sessionIDList)] 113 } 114 115 //判断Cookie的合法性(每进入一个页面都需要判断合法性) 116 func (mgr *SessionMgr) CheckCookieValid(w http.ResponseWriter, r *http.Request) string { 117 var cookie, err = r.Cookie(mgr.mCookieName) 118 119 if cookie == nil || 120 err != nil { 121 return “” 122 } 123 124 mgr.mLock.Lock() 125 defer mgr.mLock.Unlock() 126 127 sessionID := cookie.Value 128 129 if session, ok := mgr.mSessions[sessionID]; ok { 130 session.mLastTimeAccessed = time.Now() //判断合法性的同时,更新最后的访问时间 131 return sessionID 132 } 133 134 return “” 135 } 136 137 //更新最后访问时间 138 func (mgr *SessionMgr) GetLastAccessTime(sessionID string) time.Time { 139 mgr.mLock.RLock() 140 defer mgr.mLock.RUnlock() 141 142 if session, ok := mgr.mSessions[sessionID]; ok { 143 return session.mLastTimeAccessed 144 } 145 146 return time.Now() 147 } 148 149 //GC回收 150 func (mgr *SessionMgr) GC() { 151 mgr.mLock.Lock() 152 defer mgr.mLock.Unlock() 153 154 for sessionID, session := range mgr.mSessions { 155 //删除超过时限的session 156 if session.mLastTimeAccessed.Unix()+mgr.mMaxLifeTime < time.Now().Unix() { 157 delete(mgr.mSessions, sessionID) 158 } 159 } 160 161 //定时回收 162 time.AfterFunc(time.Duration(mgr.mMaxLifeTime)*time.Second, func() { mgr.GC() }) 163 } 164 165 //创建唯一ID 166 func (mgr *SessionMgr) NewSessionID() string { 167 b := make([]byte, 32) 168 if _, err := io.ReadFull(rand.Reader, b); err != nil { 169 nano := time.Now().UnixNano() //微秒 170 return strconv.FormatInt(nano, 10) 171 } 172 return base64.URLEncoding.EncodeToString(b) 173 } 174 175 //—————————————————————————— 176 /*会话*/ 177 type Session struct { 178 mSessionID string //唯一id 179 mLastTimeAccessed time.Time //最后访问时间 180 mValues map[interface{}]interface{} //其它对应值(保存用户所对应的一些值,比如用户权限之类) 181 }
2.使用方法
①定义一个全局变量
1 var sessionMgr *Helper.SessionMgr = nil //session管理器
②在程序入口处,创建一个session的对象
1 //创建session管理器,”TestCookieName”是浏览器中cookie的名字,3600是浏览器cookie的有效时间(秒) 2 sessionMgr = Helper.NewSessionMgr(“TestCookieName”, 3600)
③在用户登录时进行登录用户合法性判断并设置属性
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(&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 }
时间: 2024-10-29 19:42:17