4、会话

Cookie vs Session

特性 Cookie Session
存储位置 客户端(浏览器) 服务器端
存储容量 小(4KB左右) 大(受服务器内存或存储限制)
生命周期 可长期存在直到过期 通常短期存在,会话结束或超时后失效
安全性 较低(存在客户端可被窃取) 较高(关键数据存在服务端)
使用场景 用户偏好,非敏感数据 用户认证状态,购物车等敏感数据
性能影响 增加请求头大小 需要服务器资源存储和检索
可扩展性 良好(数据在客户端) 需要特殊设计支持分布式系统

Cookie

Cookie是服务器发送到用户浏览器并保存在浏览器上的一小块数据。浏览器会在之后的请求中将Cookie发送回服务器,用于在无状态的HTTP协议中实现有状态的会话管理。

设置Cookie

Gin提供了简便的方法来设置Cookie:

func SetCookie(c *gin.Context) {
    // 设置简单的Cookie
    c.SetCookie("simple_cookie", "value", 3600, "/", "localhost", false, true)   
    c.String(200, "Cookie已设置")
}

Cookie参数:

参数 类型 说明 默认值 示例
name string Cookie的名称 (必填) "user_id"
value string Cookie的值 (必填) "12345"
maxAge int 有效期(秒) 0 3600 (1小时)
path string Cookie生效的路径 "/" "/admin"
domain string Cookie生效的域名 当前域 "example.com"
secure bool 是否只在HTTPS下传输 false true
httpOnly bool 是否允许JavaScript访问 false true

读取Cookie

func GetCookie(c *gin.Context) {
    // 获取Cookie值
    cookie, err := c.Cookie("simple_cookie")
    
    if err != nil {
        c.String(200, "Cookie not found")
        return
    }
    
    c.String(200, "Cookie value: %s", cookie)
}

删除Cookie

删除Cookie可以通过设置负的过期时间实现:

func DeleteCookie(c *gin.Context) {
    // 设置maxAge为-1即可删除Cookie
    c.SetCookie("simple_cookie", "", -1, "/", "localhost", false, true)
    c.String(200, "Cookie已删除")
}

Session

Session是服务器用来存储特定用户会话所需信息的机制。Session通常使用唯一的标识符(Session ID)跟踪用户,该标识符通常存储在Cookie中。

Gin本身不提供Session管理,需要使用第三方库,如:

下面我们以gin-contrib/sessions为例:

安装:

go get -u github.com/gin-contrib/sessions

示例代码:

import (
    "github.com/gin-gonic/gin"
    "github.com/gin-contrib/sessions"
    "github.com/gin-contrib/sessions/cookie"
)

func main() {
    r := gin.Default()
    
    // 创建基于Cookie的存储引擎
    store := cookie.NewStore([]byte("secret_key"))
    
    // 设置Session中间件,指定Session名称为mysession
    r.Use(sessions.Sessions("mysession", store))
    
    // ... 路由设置
    r.Run(":8080")
}

Session存储选项

gin-contrib/sessions支持多种存储后端:

存储选项 导入包 初始化代码 适用场景
Cookie存储 "github.com/gin-contrib/sessions/cookie" store := cookie.NewStore([]byte("secret")) 开发环境,简单应用
Redis存储 "github.com/gin-contrib/sessions/redis" store, _ := redis.NewStore(10, "tcp", "localhost:6379", "", []byte("secret")) 生产环境,需要扩展
Memcached存储 "github.com/gin-contrib/sessions/memcached" store, _ := memcached.NewStore([]string{"localhost:11211"}, "", []byte("secret")) 高性能缓存需求
MongoDB存储 "github.com/gin-contrib/sessions/mongo" store, _ := mongo.NewStore(mongoSession, "database", "collection", 3600, []byte("secret")) 需要持久化会话
内存存储 "github.com/gin-contrib/sessions/memstore" store := memstore.NewStore([]byte("secret")) 单机开发环境

Session操作

基本的Session操作包括读取、设置和删除:

// 设置Session值
func SetSession(c *gin.Context) {
    session := sessions.Default(c)
    session.Set("user_id", 123)
    session.Set("username", "john_doe")
    // 保存会话,这一步是必须的
    session.Save()
    
    c.JSON(200, gin.H{"message": "Session已设置"})
}

// 获取Session值
func GetSession(c *gin.Context) {
    session := sessions.Default(c)
    userId := session.Get("user_id")
    username := session.Get("username")
    
    c.JSON(200, gin.H{
        "user_id":  userId,
        "username": username,
    })
}

// 删除Session值
func ClearSession(c *gin.Context) {
    session := sessions.Default(c)
    session.Clear()
    session.Save()
    
    c.JSON(200, gin.H{"message": "Session已清除"})
}

// 删除特定Session键
func DeleteSessionKey(c *gin.Context) {
    session := sessions.Default(c)
    session.Delete("username")
    session.Save()
    
    c.JSON(200, gin.H{"message": "用户名已从Session中删除"})
}

常用方法

方法 说明 注意事项
sessions.Default(c) 获取会话实例 必须先配置Sessions中间件
session.Get(key) 获取会话值 返回interface{},需要类型断言
session.Set(key, value) 设置会话值 修改后必须调用Save()
session.Delete(key) 删除特定键 修改后必须调用Save()
session.Clear() 清除所有会话数据 修改后必须调用Save()
session.Save() 保存会话更改 必须在修改会话后调用
session.Options() 设置会话选项 可设置路径、域名等
session.Flashes() 获取并清除一次性消息 用于跨请求消息传递
session.AddFlash() 添加一次性消息 用于跨请求消息传递