• Gin 中的 Session(会话控制)


    Session 介绍

    session和cookie实现的底层目标是一致的,但是从根本而言实现的方法是不同的

    session 是另一种记录客户状态的机制, 不同的是 Cookie 保存在客户端浏览器中,而 session保存 在服务器上

    Session 的工作流程

    当客户端浏览器第一次访问服务器并发送请求时,服务器端会创建一个 session 对象,生成一个类似于 key,value 的键值对, 然后将 value 保存到服务器,将 key(cookie)返回到浏览器(客户)端
    浏览器下次访问时会携带 key(cookie),找到对应的 session(value)。

    Gin 官方没有给我们提供 Session 相关的文档,这个时候我们可以使用第三方的 Session 中间件来实现;

     gin-contrib/sessions 中间件支持的存储引擎:

     cookie memstore redis memcached mongodb

    基于 Cookie 存储 Session 

    1、安装 session 包

    go get github.com/gin-contrib/sessions

    2、main.go入口文件引入session 

    密钥是成对定义的,以允许密钥循环,但常见的情况是设置一个身份验证密钥和一个加密密钥 (可选)。
    -对密钥中的第一个用于身份验证,第二个用于加密。加密密钥可以设置为零或在最后一对中省略,但所有对中都需要身份验证密钥。
    建议使用32或64字节的认证密钥。加密密钥 (如果设置) 必须是16,2424或32字节来选择AES-128、AES-192或AES-256模式。

    创建基于 cookie 的存储引擎,secret8090 参数是用于加密的密钥

    设置 session 中间件,参数 mysession,指的是 session 的名字,也是 cookie 的名字 

    store 是前面创建的存储引擎,可以替换成其他存储引擎

    1. package main
    2. import (
    3. "gindemo04/models"
    4. "gindemo04/routers"
    5. "github.com/gin-contrib/sessions"
    6. "github.com/gin-contrib/sessions/cookie"
    7. "github.com/gin-gonic/gin"
    8. "html/template"
    9. )
    10. func main() {
    11. // 创建一个默认的路由引擎
    12. r := gin.Default()
    13. //自定义模板函数 注意要把这个函数放在加载模板前
    14. r.SetFuncMap(template.FuncMap{
    15. "UnixToTime": models.UnixToTime,
    16. })
    17. //加载模板 放在配置路由前面
    18. r.LoadHTMLGlob("templates/**/*")
    19. //配置静态web目录 第一个参数表示路由, 第二个参数表示映射的目录
    20. r.Static("/static", "./static")
    21. // 创建基于 cookie 的存储引擎,secret8090 参数是用于加密的密钥
    22. //搞这个中间件先去上面import引入了,然后这里再配置
    23. store := cookie.NewStore([]byte("secret8090"))
    24. // 设置 session 中间件,参数 mysession,指的是 session 的名字,也是 cookie 的名字
    25. // store 是前面创建的存储引擎,可以替换成其他存储引擎
    26. r.Use(sessions.Sessions("mysession", store))
    27. routers.AdminRoutersInit(r)
    28. routers.ApiRoutersInit(r)
    29. routers.DefaultRouters(r)
    30. r.Run(":80")
    31. }

    3、控制器配置

    1. package test
    2. import (
    3. "fmt"
    4. "gindemo04/models"
    5. "net/http"
    6. "github.com/gin-contrib/sessions"
    7. "github.com/gin-gonic/gin"
    8. )
    9. type ModelTest struct{}
    10. func (con ModelTest) Index(c *gin.Context) {
    11. //设置sessions
    12. session := sessions.Default(c)
    13. session.Set("username","卫宫士郎")
    14. session.Save() //设置sessions的时候必须调用这个save
    15. fmt.Println(models.UnixToTime(1757814260))
    16. c.HTML(http.StatusOK, "default/index.html", gin.H{
    17. "msg": "session测试内容--转换时间戳---如下:",
    18. "t": 1757814260,
    19. })
    20. }
    21. func (con ModelTest) News(c *gin.Context) {
    22. //获取session
    23. session := sessions.Default(c)
    24. username := session.Get("username")
    25. c.String(http.StatusOK, "username=%v",username)
    26. }

     4、测试

    当客户端浏览器首次访问服务端,服务器端会创建一个 session 对象,生成一个类似于 key,value 的键值对,然后将 value 保存到服务器,将 key返下发到浏览器(客户)端,生成一个cookie

    再次访问的时候,携带上次的cookie也就是key去找value;

    那么有一个问题,生产环境使用的是nginx的负载均衡模式;

    如果访问nginx,写入到了一台服务器,那么其他服务器内没有session有的key以及value怎么办?

    那么就涉及到分布式环境,将session的kv保存到数据库内了

    Redis数据库保存session

     newstore后面需要跟的内容为:

    尺寸:最大空闲连接数。网络: 服务器地址:port password:redis-password密钥是成对定义的,以允许密钥轮换,但常见的情况是设置一个认证密钥和一个加密密钥 (可选)。
    -对密钥中的第一个用于身份验证,第二个用于加密。加密密钥可以设置为零或在最后一对中省略,但所有对中都需要身份验证密钥。
    建议使用32或64字节的身份验证密钥。加密密钥 (如果设置) 必须是16,2424或32字节来选择AES-128、AES-192或AES-256模式。

    1、main.go文件配置

    1. package main
    2. import (
    3. "gindemo04/models"
    4. "gindemo04/routers"
    5. "github.com/gin-contrib/sessions"
    6. "github.com/gin-contrib/sessions/redis"
    7. "github.com/gin-gonic/gin"
    8. "html/template"
    9. )
    10. func main() {
    11. // 创建一个默认的路由引擎
    12. r := gin.Default()
    13. //自定义模板函数 注意要把这个函数放在加载模板前
    14. r.SetFuncMap(template.FuncMap{
    15. "UnixToTime": models.UnixToTime,
    16. })
    17. //加载模板 放在配置路由前面
    18. r.LoadHTMLGlob("templates/**/*")
    19. //配置静态web目录 第一个参数表示路由, 第二个参数表示映射的目录
    20. r.Static("/static", "./static")
    21. // 这里需要修改存储引擎
    22. store, _ := redis.NewStore(10, "tcp", "localhost:6379", "", []byte("secret8090"))
    23. r.Use(sessions.Sessions("mysession", store))
    24. routers.AdminRoutersInit(r)
    25. routers.ApiRoutersInit(r)
    26. routers.DefaultRouters(r)
    27. r.Run(":80")
    28. }

    2、控制器配置

    1. package test
    2. import (
    3. "fmt"
    4. "gindemo04/models"
    5. "net/http"
    6. "github.com/gin-contrib/sessions"
    7. "github.com/gin-gonic/gin"
    8. )
    9. type ModelTest struct{}
    10. func (con ModelTest) Index(c *gin.Context) {
    11. //设置sessions
    12. session := sessions.Default(c)
    13. session.Set("username","卫宫士郎")
    14. session.Save() //设置sessions的时候必须调用这个save
    15. fmt.Println(models.UnixToTime(1757814260))
    16. c.HTML(http.StatusOK, "default/index.html", gin.H{
    17. "msg": "session测试内容--转换时间戳---如下:",
    18. "t": 1757814260,
    19. })
    20. }
    21. func (con ModelTest) News(c *gin.Context) {
    22. //获取session
    23. session := sessions.Default(c)
    24. username := session.Get("username")
    25. c.String(http.StatusOK, "username=%v",username)
    26. }

    3、配置完成redis,打开cmd

    输入redis-cli查看是否安装成功

     4、查看redis是否有键值对

    5、运行我们的seesion,把v上传服务器

    再访问news

    查看redis是否保存value(cookie)

    进行加密后的

    session的过期时间配置

    查看session的配置options的结构体内,有过期时间的配置

    MaxAge的单位是秒

    在控制器的set上面进行操作:

    1. func (con ModelTest) Index(c *gin.Context) {
    2. //设置sessions
    3. session := sessions.Default(c)
    4. session.Options(sessions.Options{
    5. MaxAge: 3600 * 6 ,
    6. })
    7. session.Set("username","卫宫士郎")
    8. session.Save() //设置sessions的时候必须调用这个save
    9. fmt.Println(models.UnixToTime(1757814260))
    10. c.HTML(http.StatusOK, "default/index.html", gin.H{
    11. "msg": "session测试内容--转换时间戳---如下:",
    12. "t": 1757814260,
    13. })
    14. }

  • 相关阅读:
    记录第一次银行测试岗面试【总结几点面试不要犯得错误】
    Spring Security—OAuth 2.0 资源服务器的多租户
    新方向!文心一言X具身智能,用LLM大模型驱动智能小车
    Centos 7分区失败,进入 dracut 页面,恢复操作
    5、使用 pgAdmin4 图形化创建和管理 PostgreSQL 数据库
    Python(7)循环语句
    小程序优化实践
    如何有效地开发 Jmix 扩展组件
    Elasticsearch实现检索词自动补全(检索词补全,自动纠错,拼音补全,繁简转换) 包含demo
    Request和Response原理与详细运用
  • 原文地址:https://blog.csdn.net/m0_72264240/article/details/133793215