💜 想真正擅长编程? 从一门课程开始,100% 免费

《笔记》第三十一篇 Gin登录后获取session

第31讲 Gin登录后获取session

本讲基于视频实际讲解内容整理


一、本讲概述

HTTP 是无状态协议,服务器默认记不住"你是谁"。登录功能需要**会话(Session)**来保存登录状态。本讲讲解在 Gin 中使用 gin-contrib/sessions 中间件:登录成功后写入 Session,后续请求读取 Session 判断用户是否已登录。


二、安装 session 中间件

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

三、注册 session 中间件

3.1 基于 Cookie 的存储

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

func main() {
    r := gin.Default()

    // 用密钥创建 cookie 存储
    store := cookie.NewStore([]byte("secret-key-123"))
    // 注册中间件,session 名为 "mysession"
    r.Use(sessions.Sessions("mysession", store))

    // ... 路由
    r.Run(":8080")
}
要素 说明
[]byte("secret-key") 用于加密/签名 cookie 的密钥,生产要换成复杂随机值
"mysession" session 在 cookie 里的名字
r.Use(...) 让每个请求都能访问 session

老师强调:密钥不能太简单,否则 session 可能被伪造。这只是 cookie 存储,数据存在客户端 cookie 中(已加密签名)。


四、登录时写入 Session

4.1 设置 session 值

Go
func Login(c *gin.Context) {
    username := c.PostForm("username")
    password := c.PostForm("password")

    // 这里省略真实的账号校验,假设校验通过
    session := sessions.Default(c)
    session.Set("username", username)   // 写入用户名
    session.Save()                       // 必须 Save 才生效

    c.JSON(200, gin.H{"msg": "登录成功"})
}

关键点:session.Save() 必须调用,否则写入不会真正保存。这是初学者最容易漏的一步。


五、获取 Session(判断登录状态)

5.1 读取 session 值

Go
func Index(c *gin.Context) {
    session := sessions.Default(c)
    username := session.Get("username")   // 返回 interface{}

    if username == nil {
        // 没登录,跳转到登录页
        c.Redirect(302, "/login")
        return
    }

    c.HTML(200, "index.html", gin.H{
        "username": username.(string),
    })
}

老师说明:session.Get 返回的是 interface{},可能为 nil(未登录)。取值后通常需要类型断言成 string。

5.2 用中间件统一校验登录

把"判断是否登录"抽成中间件,避免每个 handler 都写一遍:

Go
func AuthRequired() gin.HandlerFunc {
    return func(c *gin.Context) {
        session := sessions.Default(c)
        if session.Get("username") == nil {
            c.Redirect(302, "/login")
            c.Abort()   // 阻止继续往下执行
            return
        }
        c.Next()
    }
}
Go
// 需要登录的路由加上该中间件
r.GET("/post/new", AuthRequired(), controller.NewPostPage)

老师强调:c.Abort() 很关键,校验不通过时要立刻中断,否则 handler 还会继续执行。


六、退出登录(销毁 Session)

Go
func Logout(c *gin.Context) {
    session := sessions.Default(c)
    session.Delete("username")   // 删除指定键
    // 或 session.Clear() 清空全部
    session.Save()
    c.Redirect(302, "/login")
}

七、本讲小结

知识点 要点
安装 gin-contrib/sessions
注册 r.Use(sessions.Sessions("名", store))
写入 session.Set("k", v); session.Save()
读取 session.Get("k")(返回 interface{})
必须 Save 不 Save 不生效
登录校验 抽成中间件 + c.Abort()
退出 session.Delete / Clear + Save

八、课后练习

  1. 安装 gin-contrib/sessions,在 main 中注册 cookie 存储中间件
  2. 在 Login 中校验通过后写入 username 到 session 并 Save()
  3. 在 Index 中读取 session,未登录则跳转到 /login
  4. 写一个 AuthRequired 中间件,保护"发帖"等需要登录的路由
  5. 实现"退出登录":删除 session 中的 username 并跳转
  6. 思考:cookie 存储和把 session 存到 Redis 各有什么优缺点?