140 lines
4.2 KiB
Markdown
140 lines
4.2 KiB
Markdown
# 6.3 Almacenamiento de sesiones
|
|
|
|
Introducimos los principios de un manejador de sesiones simple en la sección anterior, y entre otras cosas, definimos una interfaz de almacenamiento de sesión. En esta sección, voy a mostrarte un ejemplo de un motor de sesiones basado en memoria que implementa esa interfaz. Puedes mejorar este a otros mecanísmos de almacenamiento también.
|
|
```
|
|
package memory
|
|
|
|
import (
|
|
"container/list"
|
|
"github.com/astaxie/session"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
var pder = &Provider{list: list.New()}
|
|
|
|
type SessionStore struct {
|
|
sid string // identificador único de sesión
|
|
timeAccessed time.Time // último tiempo de acceso
|
|
value map[interface{}]interface{} // valor de la sesión accedida
|
|
}
|
|
|
|
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
|
|
}
|
|
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 // bloqueo
|
|
sessions map[string]*list.Element // guardar en memoria
|
|
list *list.List // recikector de basura
|
|
}
|
|
|
|
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)
|
|
}
|
|
```
|
|
|
|
El ejmplo superior implementa un mecanismo de almacenamiento de sesiones en memoria. Usa la función `init()` para registrar este motor de almacenamiento al manejador de sesiones. ¿Cómo registramos este motor en nuestro programa principal?
|
|
```
|
|
import (
|
|
"github.com/astaxie/session"
|
|
_ "github.com/astaxie/session/providers/memory"
|
|
)
|
|
```
|
|
Usamos el mecanismo de importación del guión bajo (que invoca a la funcuón `init` del paquete automáticamente) para registrar este motor al manejador de sesiones. Luego usamos el siguiente código para inicializar el manejador de sesión.
|
|
```
|
|
var globalSessions *session.Manager
|
|
|
|
// initialize in init() function
|
|
func init() {
|
|
globalSessions, _ = session.NewManager("memory", "gosessionid", 3600)
|
|
go globalSessions.GC()
|
|
}
|
|
```
|
|
## Enlaces
|
|
|
|
- [Índice](preface.md)
|
|
- Sección previa: [Cómo usar sesiones en Go](06.2.md)
|
|
- Siguiente sección: [Prevenir el hijacking de sesión](06.4.md)
|