Go实现Session
2017-06-12 17:13
169 查看
Go实现Session
//-------------session_implements----------------- //Session操作接口,不同存储方式的Sesion操作不同,实现也不同 type Session interface { Set(key, value interface{}) Get(key interface{}) interface{} Remove(key interface{}) error GetId() string } //session实现 type SessionFromMemory struct { //唯一标示 sid string lock sync.Mutex //一把互斥锁 lastAccessedTime time.Time //最后访问时间 maxAge int64 //超时时间 data map[interface{}]interface{} //主数据 } //实例化 func newSessionFromMemory() *SessionFromMemory { return &SessionFromMemory{ data: make(map[interface{}]interface{}), maxAge: 60 * 30, //默认30分钟 } } //同一个会话均可调用,进行设置,改操作必须拥有排斥锁 func (si *SessionFromMemory) Set(key, value interface{}) { si.lock.Lock() defer si.lock.Unlock() si.data[key] = value } func (si *SessionFromMemory) Get(key interface{}) interface{} { if value := si.data[key]; value != nil { return value } return nil } func (si *SessionFromMemory) Remove(key interface{}) error { if value := si.data[key]; value != nil { delete(si.data, key) } return nil } func (si *SessionFromMemory) GetId() string { return si.sid } //--------------session_from--------------------------- //session存储方式接口,可以存储在内存,数据库或者文件 //分别实现该接口即可 //如存入数据库的CRUD操作 type Storage interface { //初始化一个session,id根据需要生成后传入 InitSession(sid string, maxAge int64) (Session, error) //根据sid,获得当前session SetSession(session Session) error //销毁session DestroySession(sid string) error //回收 GCSession() } //session来自内存 type FromMemory struct { //由于session包含所有的请求 //并行时,保证数据独立、一致、安全 lock sync.Mutex //互斥锁 sessions map[string]Session } //实例化一个内存实现 func newFromMemory() *FromMemory { return &FromMemory{ sessions: make(map[string]Session, 0), } } //初始换会话session,这个结构体操作实现Session接口 func (fm *FromMemory) InitSession(sid string, maxAge int64) (Session, error) { fm.lock.Lock() defer fm.lock.Unlock() newSession := newSessionFromMemory() newSession.sid = sid if maxAge != 0 { newSession.maxAge = maxAge } newSession.lastAccessedTime = time.Now() fm.sessions[sid] = newSession //内存管理map return newSession, nil } //设置 func (fm *FromMemory) SetSession(session Session) error { fm.sessions[session.GetId()] = session return nil } //销毁session func (fm *FromMemory) DestroySession(sid string) error { if _, ok := fm.sessions[sid]; ok { delete(fm.sessions, sid) return nil } return nil } //监判超时 func (fm *FromMemory) GCSession() { sessions := fm.sessions //fmt.Println("gc session") if len(sessions) < 1 { return } //fmt.Println("current active sessions ", sessions) for k, v := range sessions { t := (v.(*SessionFromMemory).lastAccessedTime.Unix()) + (v.(*SessionFromMemory).maxAge) if t < time.Now().Unix() { //超时了 fmt.Println("timeout-------->", v) delete(fm.sessions, k) } } } //--------------session_manager---------------------- //管理Session,实际操作cookie,Storage //由于该结构体是整个应用级别的,写、修改都需要枷锁 type SessionManager struct { //session数据最终需要在客户端(浏览器)和服务器各存一份 //客户端时,存放在cookie中 cookieName string //存放方式,如内存,数据库,文件 storage Storage //超时时间 maxAge int64 //由于session包含所有的请求 //并行时,保证数据独立、一致、安全 lock sync.Mutex } //实例化一个session管理器 func NewSessionManager() *SessionManager { sessionManager := &SessionManager{ cookieName: "lzy-cookie", storage: newFromMemory(), //默认以内存实现 maxAge: 60 * 30, //默认30分钟 } go sessionManager.GC() return sessionManager } func (m *SessionManager) GetCookieN() string { return m.cookieName } //先判断当前请求的cookie中是否存在有效的session,存在返回,不存在创建 func (m *SessionManager) BeginSession(w http.ResponseWriter, r *http.Request) Session { //防止处理时,进入另外的请求 m.lock.Lock() defer m.lock.Unlock() cookie, err := r.Cookie(m.cookieName) if err != nil || cookie.Value == "" { //如果当前请求没有改cookie名字对应的cookie fmt.Println("-----------> current session not exists") //创建一个 sid := m.randomId() //根据保存session方式,如内存,数据库中创建 session, _ := m.storage.InitSession(sid, m.maxAge) //该方法有自己的锁,多处调用到 maxAge := m.maxAge if maxAge == 0 { maxAge = session.(*SessionFromMemory).maxAge } //用session的ID于cookie关联 //cookie名字和失效时间由session管理器维护 cookie := http.Cookie{ Name: m.cookieName, //这里是并发不安全的,但是这个方法已上锁 Value: url.QueryEscape(sid), //转义特殊符号@#¥%+*-等 Path: "/", HttpOnly: true, MaxAge: int(maxAge), Expires: time.Now().Add(time.Duration(maxAge)), } http.SetCookie(w, &cookie) //设置到响应中 return session } else { //如果存在 sid, _ := url.QueryUnescape(cookie.Value) //反转义特殊符号 session := m.storage.(*FromMemory).sessions[sid] //从保存session介质中获取 fmt.Println("session --------->", session) if session == nil { fmt.Println("-----------> current session is nil") //创建一个 //sid := m.randomId() //根据保存session方式,如内存,数据库中创建 newSession, _ := m.storage.InitSession(sid, m.maxAge) //该方法有自己的锁,多处调用到 maxAge := m.maxAge if maxAge == 0 { maxAge = newSession.(*SessionFromMemory).maxAge } //用session的ID于cookie关联 //cookie名字和失效时间由session管理器维护 newCookie := http.Cookie{ Name: m.cookieName, //这里是并发不安全的,但是这个方法已上锁 Value: url.QueryEscape(sid), //转义特殊符号@#¥%+*-等 Path: "/", HttpOnly: true, MaxAge: int(maxAge), Expires: time.Now().Add(time.Duration(maxAge)), } http.SetCookie(w, &newCookie) //设置到响应中 return newSession } fmt.Println("-----------> current session exists") return session } } //更新超时 func (m *SessionManager) Update(w http.ResponseWriter, r *http.Request) { m.lock.Lock() defer m.lock.Unlock() cookie, err := r.Cookie(m.cookieName) if err != nil { return } t := time.Now() sid, _ := url.QueryUnescape(cookie.Value) sessions := m.storage.(*FromMemory).sessions session := sessions[sid].(*SessionFromMemory) session.lastAccessedTime = t sessions[sid] = session if m.maxAge != 0 { cookie.MaxAge = int(m.maxAge) } else { cookie.MaxAge = int(session.maxAge) } http.SetCookie(w, cookie) } //通过ID获取session func (m *SessionManager) GetSessionById(sid string) Session { session := m.storage.(*FromMemory).sessions[sid] return session } //是否内存中存在 func (m *SessionManager) MemoryIsExists(sid string) bool { _, ok := m.storage.(*FromMemory).sessions[sid] if ok { return true } return false } //手动销毁session,同时删除cookie func (m *SessionManager) Destroy(w http.ResponseWriter, r *http.Request) { cookie, err := r.Cookie(m.cookieName) if err != nil || cookie.Value == "" { return } else { m.lock.Lock() defer m.lock.Unlock() sid, _ := url.QueryUnescape(cookie.Value) m.storage.DestroySession(sid) cookie2 := http.Cookie{ MaxAge: 0, Name: m.cookieName, Value: "", Path: "/", Expires: time.Now().Add(time.Duration(0)), } http.SetCookie(w, &cookie2) } } func (m *SessionManager) CookieIsExists(r *http.Request) bool { _, err := r.Cookie(m.cookieName) if err != nil { return false } return true } //开启每个会话,同时定时调用该方法 //到达session最大生命时,且超时时。回收它 func (m *SessionManager) GC() { m.lock.Lock() defer m.lock.Unlock() m.storage.GCSession() //在多长时间后执行匿名函数,这里指在某个时间后执行GC time.AfterFunc(time.Duration(m.maxAge*10), func() { m.GC() }) } //是否将session放入内存(操作内存)默认是操作内存 func (m *SessionManager) IsFromMemory() { m.storage = newFromMemory() } //是否将session放入数据库(操作数据库) func (m *SessionManager) IsFromDB() { //TODO //关于存数据库暂未实现 } func (m *SessionManager) SetMaxAge(t int64) { m.maxAge = t } //如果你自己实现保存session的方式,可以调该函数进行定义 func (m *SessionManager) SetSessionFrom(storage Storage) { m.storage = storage } //生成一定长度的随机数 func (m *SessionManager) randomId() string { b := make([]byte, 32) if _, err := io.ReadFull(rand.Reader, b); err != nil { return "" } //加密 return base64.URLEncoding.EncodeToString(b) }
相关文章推荐
- 如何使 FlashGet "正常合法" 下载 Session 中的自定义文件链接呢? JSP/Servlet 实现!
- 在CGI中实现session的想法和实现
- 利用HttpSessionListener实现网站在线人数统计功能
- ASP.NET 中 Session 实现原理浅析 [2] 状态管理器 (转)
- ASP.NET 中 Session 实现原理浅析 [1] 会话的建立流程
- session 的cgi 简单实现
- 使用Session记录页面地址和实现页面返回功能
- php生成SessionID和图片校验码的思路和实现
- ASP.NET 中 Session 实现原理浅析 [1] 会话的建立流程
- 轻松实现session的mysql处理
- ASP.NET 中 Session 实现原理浅析 [2] 状态管理器
- HttpSessionBindingListener实现与应用
- php实现多session并发运行
- wap页面的返回实现以及go任务
- 用jb7+weblogic6.1实现 客户端+无状态sessionbean+实体bean的调用
- ASP.NET 中 Session 实现原理浅析 [1] 会话的建立流程
- ASP.NET 中 Session 实现原理浅析 [1] 会话的建立流程
- 在CGI中实现session的想法和实现
- User Session Filter实现
- ASP.NET 中 Session 实现原理浅析 [2] 状态管理器