Gin session库
本文讨论的Gin相关的session库为:https://github.com/gin-contrib/sessions
Redis-based session源码分析
gin-contrib/sessions这个库支持多种session的实现,例如:cookie-based session / Redis-based session / memcached Session。这里我们主要分析Redis-based session的实现代码。cookie-based session和Redis-based session的优缺点比较:
优点 | 缺点 | |
---|---|---|
cookie-based | 简单,无需引入第三方存储,不占用服务器存储资源 | 不安全,受浏览器限制,控制起来不灵活(例如从服务端设置“登出”用户) |
Redis-based | 相对安全,控制更加灵活,适合存敏感信息 | 占用服务器资源 |
session.Sessions中间件
在Gin中,通常以中间件的方式进行session管理。中间件的使用方式,我们应该都已经比较熟悉了。相应的HandlerFunc在gin-contrib/sessionssessions.go中:
func Sessions(name string, store Store) gin.HandlerFunc {
return func(c *gin.Context) {
s := &session{
name, c.Request, store, nil, false, c.Writer}
c.Set(DefaultKey, s)
defer context.Clear(c.Request)
c.Next()
}
}
这里就干了一件事情:把request和store信息Set到Gin context中的Keys里,方便Handler中进行使用。这里的store为redis的接口。由此可以判断,业务Handler中肯定是从context里取出session,进行应用,我们后面来验证。
Handler中获取session
在Handler中,我们通过session := sessions.Default(c)
来获取session,从而对session进行检查和处理。
sessions.go:
// shortcut to get session
func Default(c *gin.Context) Session {
return c.MustGet(DefaultKey).(Session)
}
Handler中Set & Save session
Set()和Save()分别是设置和保存session信息的方法。gin-contrib/sessions的底层引用的是gorilla/sessions,Session struct的结构如下,其中的Values这个map用于存储session信息的键值对。
// Session stores the values and optional configuration for a session.
type Session struct {
// The ID of the session, generated by stores. It should not be used for
// user data.
ID string
// Values contains the user-data for the session.
Values map[interface{
}]interface{
}
Options *Options
IsNew bool
store Store
name string
}
所以Set()方法更新的是上面的Values:
func