因为http是无状态、短连接,如何保存客户端和服务器直接的会话状态呢?可以使用session。
session 是另一种记录客户状态的机制,不同的是 Cookie 保存在客户端浏览器中,而session保存在服务器上。
主要功能:
工作流程:
当客户端浏览器第一次访问服务器并发送请求时,服务器端会创建一个session 对象,生成一个类似于 key-value 的键值对,然后将 value 保存到服务器 ,将 key(cookie)返回到浏览器(客户)端。浏览器下次访问时会携带 key(cookie),找到对应的 session(value)。
gin 本身没有对session的支持,可以使用第三方中间件。
下载:
go get github.com/gin-contrib/sessions
导入:
import "github.com/gin-contrib/sessions"
该中间件提供了很多后端支持:
type Session interface {
// ID of the session, generated by stores. It should not be used for user data.
ID() string
// Get returns the session value associated to the given key.
Get(key interface{}) interface{}
// Set sets the session value associated to the given key.
Set(key interface{}, val interface{})
// Delete removes the session value associated to the given key.
Delete(key interface{})
// Clear deletes all values in the session.
Clear()
// AddFlash adds a flash message to the session.
// A single variadic argument is accepted, and it is optional: it defines the flash key.
// If not defined "_flash" is used by default.
AddFlash(value interface{}, vars ...string)
// Flashes returns a slice of flash messages from the session.
// A single variadic argument is accepted, and it is optional: it defines the flash key.
// If not defined "_flash" is used by default.
Flashes(vars ...string) []interface{}
// Options sets configuration for a session.
Options(Options)
// Save saves all sessions used during the current request.
Save() error
}
package main
import (
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin"
)
func Handler(c *gin.Context) {
session := sessions.Default(c)
// 获得session的Get
if session.Get("hello") != "world" {
// 设置
session.Set("hello", "world")
// 保存
session.Save()
}
c.JSON(200, gin.H{"hello": session.Get("hello")})
}
func main() {
r := gin.Default()
store := cookie.NewStore([]byte("secret"))
// 使用session中间件
r.Use(sessions.Sessions("mysession", store))
r.GET("/hello", Handler)
r.Run()
}
浏览器输入:localhost:8080/hello
查看结果:
package main
import (
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin"
)
func Handler(c *gin.Context) {
sessionA := sessions.DefaultMany(c, "a")
sessionB := sessions.DefaultMany(c, "b")
if sessionA.Get("hello") != "world!" {
sessionA.Set("hello", "world!")
sessionA.Save()
}
if sessionB.Get("hello") != "world?" {
sessionB.Set("hello", "world?")
sessionB.Save()
}
c.JSON(200, gin.H{
"a": sessionA.Get("hello"),
"b": sessionB.Get("hello"),
})
}
func main() {
r := gin.Default()
store := cookie.NewStore([]byte("secret"))
sessionNames := []string{"a", "b"}
r.Use(sessions.SessionsMany(sessionNames, store))
r.GET("/hello", Handler)
r.Run()
}
浏览器输入:localhost:8080/hello
查看结果:
go get github.com/gin-contrib/sessions/redis
实例演示:
package main
import (
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/redis"
"github.com/gin-gonic/gin"
)
//设置session
func setSession(c *gin.Context) {
//初始化 session 对象
session := sessions.Default(c)
//设置过期时间,单位是秒
session.Options(sessions.Options{
MaxAge: 3600,
})
//设置 Session
session.Set("username", "Psych")
session.Save()
c.String(200, "session设置成功: %v", session.Get("username"))
}
//获取session
func getSession(c *gin.Context) {
// 初始化 session 对象
session := sessions.Default(c)
// 通过 session.Get 读取 session 值
username := session.Get("username")
c.String(200, "查询session成功: %v", username)
}
func main() {
engine := gin.Default()
// 初始化基于 redis 的存储引擎
//第 1 个参数 - redis 最大的空闲连接数
//第 2 个参数 - 数通信协议 tcp 或者 udp
//第 3 个参数 - redis 地址, 格式,host:port
//第 4 个参数 - redis 密码
//第 5 个参数 - session 加密密钥
store, _ := redis.NewStore(10, "tcp", "localhost:6379", "", []byte("secret3652"))
// 设置 session 中间件,参数 mysession,指的是 session 的名字,也是 cookie 的名字
// store 是前面创建的存储引擎,我们可以替换成其他存储引擎
engine.Use(sessions.Sessions("mysession", store))
engine.GET("/setSession", setSession)
engine.GET("/getSession", getSession)
engine.Run()
}
首先打开redis服务端
然后浏览器输入localhost:8080/setSession
显示结果:
将url更改为:localhost:8080/getSession
查看结果
参考:https://pkg.go.dev/github.com/gin-contrib/sessions#section-readme