首页 文章资讯内容详情

Golang的session管理器

2026-06-01 4 花语

本文内容纲要:

对于一些需要对用户进行管理(比如验证操作的权限等)的站点来说,session管理器是必不可少的。下面实现了一个线程安全的简单session管理类。

生产环境:golang1.4.2+win7x64

golang1.4.2+centos6.5×64

1.代码如下:

packageHelper import( "crypto/rand" "encoding/base64" "io" "net/http" "net/url" "strconv" "sync" "time" ) /*Session会话管理*/ typeSessionMgrstruct{ mCookieNamestring//客户端cookie名称 mLocksync.RWMutex//互斥(保证线程安全) mMaxLifeTimeint64//垃圾回收时间 mSessionsmap[string]*Session//保存session的指针[sessionID]=session } //创建会话管理器(cookieName:在浏览器中cookie的名字;maxLifeTime:最长生命周期) funcNewSessionMgr(cookieNamestring,maxLifeTimeint64)*SessionMgr{ mgr:=&SessionMgr{mCookieName:cookieName,mMaxLifeTime:maxLifeTime,mSessions:make(map[string]*Session)} //启动定时回收 gomgr.GC() returnmgr } //在开始页面登陆页面,开始Session func(mgr*SessionMgr)StartSession(whttp.ResponseWriter,r*http.Request)string{ mgr.mLock.Lock() defermgr.mLock.Unlock() //无论原来有没有,都重新创建一个新的session newSessionID:=url.QueryEscape(mgr.NewSessionID()) //存指针 varsession*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) returnnewSessionID } //结束Session func(mgr*SessionMgr)EndSession(whttp.ResponseWriter,r*http.Request){ cookie,err:=r.Cookie(mgr.mCookieName) iferr!=nil||cookie.Value==""{ return }else{ mgr.mLock.Lock() defermgr.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(sessionIDstring){ mgr.mLock.Lock() defermgr.mLock.Unlock() delete(mgr.mSessions,sessionID) } //设置session里面的值 func(mgr*SessionMgr)SetSessionVal(sessionIDstring,keyinterface{},valueinterface{}){ mgr.mLock.Lock() defermgr.mLock.Unlock() ifsession,ok:=mgr.mSessions[sessionID];ok{ session.mValues[key]=value } } //得到session里面的值 func(mgr*SessionMgr)GetSessionVal(sessionIDstring,keyinterface{})(interface{},bool){ mgr.mLock.RLock() defermgr.mLock.RUnlock() ifsession,ok:=mgr.mSessions[sessionID];ok{ ifval,ok:=session.mValues[key];ok{ returnval,ok } } returnnil,false } //得到sessionID列表 func(mgr*SessionMgr)GetSessionIDList()[]string{ mgr.mLock.RLock() defermgr.mLock.RUnlock() sessionIDList:=make([]string,0) fork,_:=rangemgr.mSessions{ sessionIDList=append(sessionIDList,k) } returnsessionIDList[0:len(sessionIDList)] } //判断Cookie的合法性(每进入一个页面都需要判断合法性) func(mgr*SessionMgr)CheckCookieValid(whttp.ResponseWriter,r*http.Request)string{ varcookie,err=r.Cookie(mgr.mCookieName) ifcookie==nil|| err!=nil{ return"" } mgr.mLock.Lock() defermgr.mLock.Unlock() sessionID:=cookie.Value ifsession,ok:=mgr.mSessions[sessionID];ok{ session.mLastTimeAccessed=time.Now()//判断合法性的同时,更新最后的访问时间 returnsessionID } return"" } //更新最后访问时间 func(mgr*SessionMgr)GetLastAccessTime(sessionIDstring)time.Time{ mgr.mLock.RLock() defermgr.mLock.RUnlock() ifsession,ok:=mgr.mSessions[sessionID];ok{ returnsession.mLastTimeAccessed } returntime.Now() } //GC回收 func(mgr*SessionMgr)GC(){ mgr.mLock.Lock() defermgr.mLock.Unlock() forsessionID,session:=rangemgr.mSessions{ //删除超过时限的session ifsession.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()//微秒 returnstrconv.FormatInt(nano,10) } returnbase64.URLEncoding.EncodeToString(b) } //—————————————————————————— /*会话*/ typeSessionstruct{ mSessionIDstring//唯一id mLastTimeAccessedtime.Time//最后访问时间 mValuesmap[interface{}]interface{}//其它对应值(保存用户所对应的一些值,比如用户权限之类) }

2.使用方法

①定义一个全局变量 1varsessionMgr*Helper.SessionMgr=nil//session管理器

②在程序入口处,创建一个session的对象

1//创建session管理器,”TestCookieName”是浏览器中cookie的名字,3600是浏览器cookie的有效时间(秒) 2sessionMgr=Helper.NewSessionMgr("TestCookieName",3600)

③在用户登录时进行登录用户合法性判断并设置属性

1//处理登录 2funclogin(whttp.ResponseWriter,r*http.Request){ 3ifr.Method=="GET"{ 4t,_:=template.ParseFiles("web/MgrSvr_login.html") 5t.Execute(w,nil) 6 7}elseifr.Method=="POST"{ 8//请求的是登陆数据,那么执行登陆的逻辑判断 9r.ParseForm() 10 11//可以使用template.HTMLEscapeString()来避免用户进行js注入 12username:=r.FormValue("username") 13password:=r.FormValue("password") 14 15//在数据库中得到对应数据 16varuserIDint=0 17 18userRow:=db.QueryRow(loginUserQuery,username,password) 19userRow.Scan(&userID) 20 21//TODO:判断用户名和密码 22ifuserID!=0{ 23//创建客户端对应cookie以及在服务器中进行记录 24varsessionID=sessionMgr.StartSession(w,r) 25 26varloginUserInfo=UserInfo{ID:userID,UserName:username,Password:password,Alias:alias, 27Desc:desc,ChannelAuth:channel_authority,IsSuperAdmin:is_super_admin,IsNewClientAuth:is_newclient_authority, 28IsPayAuth:is_pay_authority,IsItemsAuth:is_itmes_authority,IsRealtimeAuth:is_realtime_authority, 29IsPayCodeAuth:is_paycode_authority,IsUserAuth:is_user_authority,IsBgOpAuth:is_bgop_authority,IsHZRaidenNMMWeak:is_hz_raidenn_mmweak, 30IsManualDataMgr:is_manual_data_mgr,IsManualDataQuery:is_manual_data_query} 31 32//踢除重复登录的 33varonlineSessionIDList=sessionMgr.GetSessionIDList() 34 35for_,onlineSessionID:=rangeonlineSessionIDList{ 36ifuserInfo,ok:=sessionMgr.GetSessionVal(onlineSessionID,"UserInfo");ok{ 37ifvalue,ok:=userInfo.(UserInfo);ok{ 38ifvalue.ID==userID{ 39sessionMgr.EndSessionBy(onlineSessionID) 40} 41} 42} 43} 44 45//设置变量值 46sessionMgr.SetSessionVal(sessionID,"UserInfo",loginUserInfo) 47 48//TODO设置其它数据 49 50//TODO转向成功页面 51 52return 53} 54} 55}

③在用户退出时删除对应session

1//处理退出 2funclogout(whttp.ResponseWriter,r*http.Request){ 3sessionMgr.EndSession(w,r)//用户退出时删除对应session 4http.Redirect(w,r,"/login",http.StatusFound) 5return 6}

④在每个页面中进行用户合法性验证

1functest_session_valid(whttp.ResponseWriter,r*http.Request){ 2varsessionID=sessionMgr.CheckCookieValid(w,r) 3 4ifsessionID==""{ 5http.Redirect(w,r,"/login",http.StatusFound) 6return 7} 8}

本文内容总结:

原文链接:https://www.cnblogs.com/chevin/p/5669940.html