[question] Sessions not persisted after server restart?
jerlam06 opened this issue · 2 comments
I am not sure if it is a normal behavior or not. My sessions are persisted correctly while my server is running, but as soon as I restart it the sessions fail to be retrieved:
package session
import (
"encoding/gob"
"fmt"
"net/http"
"github.com/jerlam06/go-gql-server/internal/logger"
myredis "github.com/jerlam06/go-gql-server/pkg/redis"
"github.com/jerlam06/go-gql-server/pkg/utils"
"github.com/gorilla/sessions"
"gopkg.in/boj/redistore.v1"
)
var (
//Store Redis store
Store *redistore.RediStore
sessionStoreSecret string = utils.MustGet("REDIS_SESSION_STORE_SECRET")
domainName string = utils.MustGet("GQL_SERVER_HOST")
sessionTimeOut int
)
// SessionObj struct that hold the session
type SessionObj struct {
ID string
Email string
Username string
PublicID int
}
// InitSessionStore Create session store
func InitSessionStore() {
sessionTimeOut = 300
rediStore, err := redistore.NewRediStoreWithPool(myredis.Pool, []byte(sessionStoreSecret))
rediStore.DefaultMaxAge = sessionTimeOut
if err != nil {
panic(err)
}
Store = rediStore
logger.Info("[Redis Store] Registering session object")
gob.Register(SessionObj{})
}
// GetSession get the session
func GetSession(r *http.Request, sessName, sessKey string) (sessObj *SessionObj, err error) {
// Get a session.
sess, err := Store.Get(r, sessName)
if err != nil {
logger.Error(err.Error())
}
fmt.Println(sess)
if obj, ok := sess.Values[sessKey].(SessionObj); !ok {
logger.Errorf("Session not found for key %s", sessKey)
err = fmt.Errorf("Session not found for key %s", sessKey)
} else {
sessObj = &obj
}
return sessObj, err
}
// SaveSession save session
func SaveSession(r *http.Request, w http.ResponseWriter, sessName, sessKey string, sessionObj *SessionObj, sessPrefix string) {
SaveSessionToStore(r, w, sessName, sessKey, sessionTimeOut, sessionObj, sessPrefix)
}
// SaveSessionToStore save session
func SaveSessionToStore(r *http.Request, w http.ResponseWriter, sessName, sessKey string, timeout int, sessionObj *SessionObj, sessPrefix string) {
Store.SetKeyPrefix(sessPrefix)
// Get a session.
sess, err := Store.Get(r, sessName)
if err != nil {
logger.Error(err.Error())
}
sess.Values[sessKey] = sessionObj
if sessionObj != nil {
logger.Infof("New session created for %s", sessKey)
}
sess.Options = &sessions.Options{
// Domain: domainName,
Path: "/",
MaxAge: timeout,
HttpOnly: true,
}
if err = sess.Save(r, w); err != nil {
logger.Fatalf("Error saving session: %v", err)
}
}
And here is in my login resolver:
session.SaveSession(&h.Request, h.ResponseWriter, sessName, "sessionID", sessObj, sessPrefix)
Note that the KEYS are still there in Redis, and the cookies are also still there in the browser.
EDIT: After some investigation, I found out what was causing this issue. I am using Store.SetKeyPrefix(sessPrefix)
when I save the session. So the KeyPrefix is set for all the lifetime of the Store. But when I restart the server, the Store is renewed and the KeyPrefix is back to default session_
.
I could "fix" it by setting the KeyPrefix when I Get() the session, but this is causing troubles because the KeyPrefix is actually "user:1_" (1 stands for the publicID of the current user). As I call Store.Get() in my Me resolver, I have no access to the current user ID yet, because I am actually trying to retrieve it from SessionObj...
The reason why I want to use "user:" + user.ID as Prefix is to handle the deletion of all the sessions of a user when the latter logs out. So that I can find all the KEYS starting with "user:1_" in my Redis store, and delete them all at once.
Do you have any idea how I could achieve that? Is using KeyPrefix the only way?
Thanks :)
This issue has been automatically marked as stale because it hasn't seen a recent update. It'll be automatically closed in a few days.