forked from go/golangs_learn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
140 lines
3.6 KiB
140 lines
3.6 KiB
4 years ago
|
# 6.3 session存储
|
||
|
上一节我们介绍了Session管理器的实现原理,定义了存储session的接口,这小节我们将示例一个基于内存的session存储接口的实现,其他的存储方式,读者可以自行参考示例来实现,内存的实现请看下面的例子代码
|
||
|
```Go
|
||
|
|
||
|
package memory
|
||
|
|
||
|
import (
|
||
|
"container/list"
|
||
|
"github.com/astaxie/session"
|
||
|
"sync"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
var pder = &Provider{list: list.New()}
|
||
|
|
||
|
type SessionStore struct {
|
||
|
sid string //session id唯一标示
|
||
|
timeAccessed time.Time //最后访问时间
|
||
|
value map[interface{}]interface{} //session里面存储的值
|
||
|
}
|
||
|
|
||
|
func (st *SessionStore) Set(key, value interface{}) error {
|
||
|
st.value[key] = value
|
||
|
pder.SessionUpdate(st.sid)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (st *SessionStore) Get(key interface{}) interface{} {
|
||
|
pder.SessionUpdate(st.sid)
|
||
|
if v, ok := st.value[key]; ok {
|
||
|
return v
|
||
|
} else {
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (st *SessionStore) Delete(key interface{}) error {
|
||
|
delete(st.value, key)
|
||
|
pder.SessionUpdate(st.sid)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (st *SessionStore) SessionID() string {
|
||
|
return st.sid
|
||
|
}
|
||
|
|
||
|
type Provider struct {
|
||
|
lock sync.Mutex //用来锁
|
||
|
sessions map[string]*list.Element //用来存储在内存
|
||
|
list *list.List //用来做gc
|
||
|
}
|
||
|
|
||
|
func (pder *Provider) SessionInit(sid string) (session.Session, error) {
|
||
|
pder.lock.Lock()
|
||
|
defer pder.lock.Unlock()
|
||
|
v := make(map[interface{}]interface{}, 0)
|
||
|
newsess := &SessionStore{sid: sid, timeAccessed: time.Now(), value: v}
|
||
|
element := pder.list.PushBack(newsess)
|
||
|
pder.sessions[sid] = element
|
||
|
return newsess, nil
|
||
|
}
|
||
|
|
||
|
func (pder *Provider) SessionRead(sid string) (session.Session, error) {
|
||
|
if element, ok := pder.sessions[sid]; ok {
|
||
|
return element.Value.(*SessionStore), nil
|
||
|
} else {
|
||
|
sess, err := pder.SessionInit(sid)
|
||
|
return sess, err
|
||
|
}
|
||
|
return nil, nil
|
||
|
}
|
||
|
|
||
|
func (pder *Provider) SessionDestroy(sid string) error {
|
||
|
if element, ok := pder.sessions[sid]; ok {
|
||
|
delete(pder.sessions, sid)
|
||
|
pder.list.Remove(element)
|
||
|
return nil
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (pder *Provider) SessionGC(maxlifetime int64) {
|
||
|
pder.lock.Lock()
|
||
|
defer pder.lock.Unlock()
|
||
|
|
||
|
for {
|
||
|
element := pder.list.Back()
|
||
|
if element == nil {
|
||
|
break
|
||
|
}
|
||
|
if (element.Value.(*SessionStore).timeAccessed.Unix() + maxlifetime) < time.Now().Unix() {
|
||
|
pder.list.Remove(element)
|
||
|
delete(pder.sessions, element.Value.(*SessionStore).sid)
|
||
|
} else {
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (pder *Provider) SessionUpdate(sid string) error {
|
||
|
pder.lock.Lock()
|
||
|
defer pder.lock.Unlock()
|
||
|
if element, ok := pder.sessions[sid]; ok {
|
||
|
element.Value.(*SessionStore).timeAccessed = time.Now()
|
||
|
pder.list.MoveToFront(element)
|
||
|
return nil
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func init() {
|
||
|
pder.sessions = make(map[string]*list.Element, 0)
|
||
|
session.Register("memory", pder)
|
||
|
}
|
||
|
```
|
||
|
上面这个代码实现了一个内存存储的session机制。通过init函数注册到session管理器中。这样就可以方便的调用了。我们如何来调用该引擎呢?请看下面的代码
|
||
|
```Go
|
||
|
|
||
|
import (
|
||
|
"github.com/astaxie/session"
|
||
|
_ "github.com/astaxie/session/providers/memory"
|
||
|
)
|
||
|
```
|
||
|
当import的时候已经执行了memory函数里面的init函数,这样就已经注册到session管理器中,我们就可以使用了,通过如下方式就可以初始化一个session管理器:
|
||
|
```Go
|
||
|
|
||
|
var globalSessions *session.Manager
|
||
|
|
||
|
//然后在init函数中初始化
|
||
|
func init() {
|
||
|
globalSessions, _ = session.NewManager("memory", "gosessionid", 3600)
|
||
|
go globalSessions.GC()
|
||
|
}
|
||
|
|
||
|
```
|
||
|
## links
|
||
|
* [目录](<preface.md>)
|
||
|
* 上一节: [Go如何使用session](<06.2.md>)
|
||
|
* 下一节: [预防session劫持](<06.4.md>)
|