对于一些需要对用户进行管理(比如验证操作的权限等)的站点来说,session管理器是必不可少的。下面实现了一个线程安全的简单session管理类。
生产环境:golang1.4.2+win7x64
golang1.4.2+centos6.5×64

1.代码如下:

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: -}
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, ) for k, _ := range mgr.mSessions {
sessionIDList = append(sessionIDList, k)
} return sessionIDList[: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, )
if _, err := io.ReadFull(rand.Reader, b); err != nil {
nano := time.Now().UnixNano() //微秒
return strconv.FormatInt(nano, )
}
return base64.URLEncoding.EncodeToString(b)
} //——————————————————————————
/*会话*/
type Session struct {
mSessionID string //唯一id
mLastTimeAccessed time.Time //最后访问时间
mValues map[interface{}]interface{} //其它对应值(保存用户所对应的一些值,比如用户权限之类)
}

2.使用方法
①定义一个全局变量

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

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

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

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

 //处理登录
func login(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
t, _ := template.ParseFiles("web/MgrSvr_login.html")
t.Execute(w, nil) } else if r.Method == "POST" {
//请求的是登陆数据,那么执行登陆的逻辑判断
r.ParseForm() //可以使用template.HTMLEscapeString()来避免用户进行js注入
username := r.FormValue("username")
password := r.FormValue("password") //在数据库中得到对应数据
var userID int = userRow := db.QueryRow(loginUserQuery, username, password)
userRow.Scan(&amp;userID) //TODO:判断用户名和密码
if userID != {
//创建客户端对应cookie以及在服务器中进行记录
var sessionID = sessionMgr.StartSession(w, r) var loginUserInfo = UserInfo{ID: userID, UserName: username, Password: password, Alias: alias,
Desc: desc, ChannelAuth: channel_authority, IsSuperAdmin: is_super_admin, IsNewClientAuth: is_newclient_authority,
IsPayAuth: is_pay_authority, IsItemsAuth: is_itmes_authority, IsRealtimeAuth: is_realtime_authority,
IsPayCodeAuth: is_paycode_authority, IsUserAuth: is_user_authority, IsBgOpAuth: is_bgop_authority, IsHZRaidenNMMWeak: is_hz_raidenn_mmweak,
IsManualDataMgr: is_manual_data_mgr, IsManualDataQuery: is_manual_data_query} //踢除重复登录的
var onlineSessionIDList = sessionMgr.GetSessionIDList() for _, onlineSessionID := range onlineSessionIDList {
if userInfo, ok := sessionMgr.GetSessionVal(onlineSessionID, "UserInfo"); ok {
if value, ok := userInfo.(UserInfo); ok {
if value.ID == userID {
sessionMgr.EndSessionBy(onlineSessionID)
}
}
}
} //设置变量值
sessionMgr.SetSessionVal(sessionID, "UserInfo", loginUserInfo) //TODO 设置其它数据 //TODO 转向成功页面 return
}
}
}

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

 //处理退出
func logout(w http.ResponseWriter, r *http.Request) {
sessionMgr.EndSession(w, r) //用户退出时删除对应session
http.Redirect(w, r, "/login", http.StatusFound)
return
}

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

 func test_session_valid(w http.ResponseWriter, r *http.Request) {
var sessionID = sessionMgr.CheckCookieValid(w, r) if sessionID == "" {
http.Redirect(w, r, "/login", http.StatusFound)
return
}
}

Golang的session管理器的更多相关文章

  1. tomcat源码阅读之session管理器(Manager)

    一.UML图分析: (一) Session: Session保存了一个客户端访问服务器时,服务器专门为这个客户端建立一个session用来保存相关的会话信息,session有一个有效时间,这个时间默认 ...

  2. how tomcat works 读书笔记九 Session管理

    在看本文之前,请先查阅相关Session与Cookie的资料. 这篇资料不错 http://blog.csdn.net/fangaoxin/article/details/6952954 Catali ...

  3. golang的包管理---vendor/dep等

    首先关于vendor 1 提出问题 我们知道,一个工程稍大一点,通常会依赖各种各样的包.而Go使用统一的GOPATH管理依赖包,且每个包仅保留一个版本.而不同的依赖包由各自的版本工具独立管理,所以当所 ...

  4. Shiro在Spring session管理

    会话管理 在shiro里面可以发现所有的用户的会话信息都会由Shiro来进行控制,那么也就是说只要是与用户有关的一切的处理信息操作都可以通过Shiro取得,实际上可以取得的信息可以有用户名.主机名称等 ...

  5. 通过Spring Session实现新一代的Session管理

    长期以来,session管理就是企业级Java中的一部分,以致于我们潜意识就认为它是已经解决的问题,在最近的记忆中,我们没有看到这个领域有很大的革新. 但是,现代的趋势是微服务以及可水平扩展的原生云应 ...

  6. TOMCAT8源码分析——SESSION管理分析(上)

    前言 对于广大java开发者而已,对于J2EE规范中的Session应该并不陌生,我们可以使用Session管理用户的会话信息,最常见的就是拿Session用来存放用户登录.身份.权限及状态等信息.对 ...

  7. Tomcat源码分析——Session管理分析(下)

    前言 在<TOMCAT源码分析——SESSION管理分析(上)>一文中我介绍了Session.Session管理器,还以StandardManager为例介绍了Session管理器的初始化 ...

  8. Tomcat源码分析——Session管理分析(上)

    前言 对于广大java开发者而已,对于J2EE规范中的Session应该并不陌生,我们可以使用Session管理用户的会话信息,最常见的就是拿Session用来存放用户登录.身份.权限及状态等信息.对 ...

  9. 008-shiro与spring web项目整合【二】认证、授权、session管理

    一.认证 1.添加凭证匹配器 添加凭证匹配器实现md5加密校验. 修改applicationContext-shiro.xml: <!-- realm --> <bean id=&q ...

随机推荐

  1. Python3 根据m3u8下载视频,批量下载ts文件并且合并

    Python3 根据m3u8下载视频,批量下载ts文件并且合并 m3u8是苹果公司推出一种视频播放标准,是一种文件检索格式,将视频切割成一小段一小段的ts格式的视频文件,然后存在服务器中(现在为了减少 ...

  2. udp丢包 处理

    转自: 自己在做UDP传输时遇到的问题,接收端没设置缓存,结果总是丢包. 看到这篇文章设置了一下接收缓存就好 *;//设置为32K setsockopt(s,SOL_SOCKET,SO_RCVBUF, ...

  3. linux交换区使用过多导致的性能问题

    近日,我们开发发现有一台配置相同的服务器跑的特别慢,相同数据量的情况下,其他服务器只要跑10分钟,这台服务器要跑50分钟,经确认,所有的应用层配置参数都相同.上去之后,发现该服务器swap使用比较多, ...

  4. Angular routing生成路由和路由的跳转

    Angular routing生成路由和路由的跳转 什么是路由 路由的目的是可以让根组件按照不同的需求动态加载不同的组件. 根据不同地址,加载不同组件,实现单页面应用. Angular 命令创建一个配 ...

  5. Huffman Implementation with Python

    Huffman Implementation with Python 码表 Token Frequency a 10 e 15 i 12 s 3 t 4 space 13 n 1 生成 Huffman ...

  6. Python语言知识总结

    1. 环境 1.1 Anaconda 抛弃python原生安装方式吧,使用Anaconda才是最省心的. 1.2 Miniconda Anaconda 太大了,Miniconda才是王道!下载链接:h ...

  7. VC++使用MapFileAndCheckSum完成自检测

    转载:https://blog.csdn.net/lekonpeng/article/details/4150464 当我们完成一个工程,编译成可执行文件后,一般是不希望这个可执行文件被人改动的,那么 ...

  8. Python3 tkinter基础 Label imag显示图片

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  9. 对应web的常用flutter应用

    例如,创建一个Text widget: new Text('Hello World', style: new TextStyle(fontSize: 32.0)) 创建一个 Image widget: ...

  10. Linux 双向 SSH 免密登录

    原理 双向,顾名思义,双方互通,此处的意思是多台 linux 两两免密登录.双向比单向多了些操作,单向只需把某一个linux的公钥发送给其他linux即可,而双向要实现集群中的每一台机器都保存其他所有 ...