设为首页 收藏本站
查看: 1314|回复: 0

[经验分享] Golang的session管理器

[复制链接]

尚未签到

发表于 2018-9-19 13:40:50 | 显示全部楼层 |阅读模式
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{} //其它对应值(保存用户所对应的一些值,比如用户权限之类)
  
}



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-594323-1-1.html 上篇帖子: Golang文件操作整理 下篇帖子: golang 的 sync.WaitGroup
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表