2018-07-17 22:00:51 +00:00
|
|
|
/*
|
|
|
|
* @Author: Bartuccio Antoine
|
|
|
|
* @Date: 2018-07-16 14:07:07
|
|
|
|
* @Last Modified by: klmp200
|
2018-07-17 22:03:38 +00:00
|
|
|
* @Last Modified time: 2018-07-18 00:03:26
|
2018-07-17 22:00:51 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
package gowebframework
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"log"
|
|
|
|
"net/http"
|
|
|
|
"net/url"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
var SESSION *SessionManager
|
|
|
|
var providers = make(map[string]Provider)
|
|
|
|
|
|
|
|
type SessionManager struct {
|
|
|
|
cookieName string // Name of the cookie on the client side
|
|
|
|
lock sync.Mutex
|
|
|
|
provider Provider
|
|
|
|
maxLifetime time.Duration
|
|
|
|
}
|
|
|
|
|
|
|
|
type Session interface {
|
|
|
|
Set(key string, value interface{}) error // set a session value
|
|
|
|
Get(key string) interface{} // get session value
|
|
|
|
Delete(key string) error // delete session value
|
|
|
|
SessionUUID() string // get the current session UUID
|
|
|
|
}
|
|
|
|
|
|
|
|
type Provider interface {
|
|
|
|
SessionInit(uuid string) (Session, error)
|
|
|
|
SessionRead(uuid string) (Session, error)
|
|
|
|
SessionDestroy(uuid string) error
|
|
|
|
SessionClearExpired(maxLifetime time.Duration)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (manager *SessionManager) generateUUID() string {
|
|
|
|
return uuid.New().String()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Launch a Clear Expired Sessions task at fixed rate
|
|
|
|
func clearExpiredSessionsCron() {
|
|
|
|
SESSION.lock.Lock()
|
|
|
|
lifetime := SESSION.maxLifetime
|
|
|
|
SESSION.lock.Unlock()
|
|
|
|
for {
|
|
|
|
SESSION.lock.Lock()
|
|
|
|
SESSION.provider.SessionClearExpired(lifetime)
|
|
|
|
SESSION.lock.Unlock()
|
|
|
|
time.Sleep(lifetime)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func SessionProviderRegister(provider Provider, providerName string) error {
|
|
|
|
if provider == nil {
|
|
|
|
return fmt.Errorf("No provider found for provider name %s", providerName)
|
|
|
|
}
|
|
|
|
if _, exists := providers[providerName]; exists {
|
|
|
|
return fmt.Errorf("Provider with name %s already exists", providerName)
|
|
|
|
}
|
|
|
|
providers[providerName] = provider
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (manager *SessionManager) GetSession(w http.ResponseWriter, r *http.Request) Session {
|
|
|
|
var session Session
|
|
|
|
manager.lock.Lock()
|
|
|
|
defer manager.lock.Unlock()
|
|
|
|
cookie, err := r.Cookie(manager.cookieName)
|
|
|
|
if err != nil || cookie.Value == "" {
|
|
|
|
// Create a new session
|
|
|
|
session_id := manager.generateUUID()
|
|
|
|
s, err := manager.provider.SessionInit(session_id)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
session = s
|
|
|
|
AddCookie(w, manager.cookieName, url.QueryEscape(session_id), manager.maxLifetime)
|
|
|
|
} else {
|
|
|
|
// Get the session
|
|
|
|
session_id, _ := url.QueryUnescape(cookie.Value)
|
|
|
|
s, err := manager.provider.SessionRead(session_id)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
session = s
|
|
|
|
}
|
|
|
|
return session
|
|
|
|
}
|
|
|
|
|
|
|
|
func newSessionManager(providerName string, cookieName string, maxLifetime time.Duration) (*SessionManager, error) {
|
|
|
|
provider, ok := providers[providerName]
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("Session error: unknown provider %s", providerName)
|
|
|
|
}
|
|
|
|
return &SessionManager{provider: provider, cookieName: cookieName, maxLifetime: maxLifetime}, nil
|
|
|
|
}
|