sessions icon indicating copy to clipboard operation
sessions copied to clipboard

Can't access certain session data with Gin sessions?

Open jeroenjacobs79 opened this issue 2 years ago • 4 comments

I originally posted this on Stack Overflow without any feedback. I am now convinced this is a bug, or odd behaviour that should be documented in the readme.

I'm new to Gin and Gin sessions, and I have a weird problem I cannot explain: It seems that session data I write in my controller can't be accessed from my middleware.

Allow me to demonstrate:

I do the following in my controller:

func OidcCallBack(c *gin.Context) {
...
	// store user info and redirect to original location
	userJsonData, err := json.Marshal(*user)
	if err != nil {
		log.Errorf("error encoding user data: %s", err.Error())
	}
	session.Set(SessionUserInfo, string(userJsonData))
	session.Save()

}

In my middleware, I want to read this session data:

func OidcMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// get our session variables
		session := sessions.Default(c)
        // some test code, this works btw
        session.Set("bla", "test")
		session.Save()
		blavar := session.Get("bla")
        // get our userinfo
		userinfo := session.Get(controllers.SessionUserInfo) // this results in nil
		log.Debug(blavar)
		if userinfo == nil {
			log.Debugf("filter incoming url: %s", c.Request.URL.String())
			session.Set(controllers.SessionRedirectTarget, c.Request.URL.String())
			session.Save()
			c.Redirect(http.StatusFound, controllers.AuthLogin)
			c.Abort()
		}
		c.Next()
	}
}

When I look in my debugger, I notice that the data set in the controller, ended up in a different place of session.store.MemStore.cache.data:

session data set in the middleware ends up in data[0], and the data set in the controller ends up in data1.

debugger output

Can someone explain me what I need to do to make sure all data ends up in the same spot, and also explain me why this happens? I can't find in any info on this in the readme file.

jeroenjacobs79 avatar Apr 05 '22 13:04 jeroenjacobs79

// create a store before
// set cookie path
store.Options(sessions.Options{
		Path:   "/",
})

details

LianYangCn avatar May 27 '22 00:05 LianYangCn

@LianYangCn Can you please elaborate what this does exactly? The path option is not documented in the code.

jeroenjacobs79 avatar Jun 21 '22 10:06 jeroenjacobs79

我也有同样的问题,就是 在不同gin.Context下(就是不同请求)session.set("some",rand)设置了很多次,最后save 在其他的gin.Context下get("some")时得到的并不是最后一次set的值,而是倒数第二次的值为什么?

zmk1173411140 avatar Jun 24 '22 01:06 zmk1173411140

@LianYangCn Can you please elaborate what this does exactly? The path option is not documented in the code.

This tells you how sessions work

if you use cookie-base, all the session will be preserved by cookies on the browser if you use a database(except cookie-based) backend, the session ID will be preserved by cookies, and the session will be preserved by the database on the server and restored the session by session ID

So, we need tell the browser to send back the cookies, like this

        r:=gin.Default()
        // ...
        // 1. create a store, no matter which backend is used
        store := memcached.NewStore(memcache.New("localhost:11211"), "", []byte("secret"))
        // store := cookie.NewStore([]byte("secret"))
	// store := gormsessions.NewStore(db, true, []byte("foo secret"))
        // store, _ := redis.NewStore(10, "tcp", "localhost:6379", "", []byte("secret"))

        // 2. setup the "Path"
	store.Options(sessions.Options{
		Path:   "/",  // keeeeeeeeeeeey
		MaxAge: int(10 * 60), //10 min
                // ...
	})
        // 3. use it
	r.Use(sessions.Sessions("foo", store))

The keeeeeeeeeeeey is the "Path" parameter, as described here

If you don't care about it, just set "/" to "Path", which means the browser will send the cookies header always.

That's it.

LianYangCn avatar Jun 28 '22 06:06 LianYangCn