ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

gin实现登录逻辑,包含cookie,session

2026/8/25 12:06:06 拓冰建站 浏览量
gin实现登录逻辑,包含cookie,session

users/login.html

{{define "users/login.html"}}
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>登录页面</title>
</head>
<body><form method="post" action="/login">username:<input style="align-content: center" type="text" name="username" onfocus="change()"><br/>password:<input type="password" name="password" onfocus="change()"><br/><input type="submit" value="login"></form><h1 id = "tag" style="color: red">{{.Message}}</h1>
</body>
<script>function change() {let tag = document.getElementById("tag");tag.innerHTML="<h1></h1>";}
</script>
</html>
{{end}}

default/index.html

{{define "default/index.html"}}
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>index页面</title>
</head>
<body>
<h1 style="color: chocolate; align-content: center">{{.Content}}</h1>
</body>
</html>
{{end}}

controllers/users.go

package controllersimport ("github.com/gin-contrib/sessions""github.com/gin-gonic/gin""net/http"
)package controllerstype Auth struct {Username stringPassword string
}const DefaultAuthInfoKey = "AUTH"func LoginGet() gin.HandlerFunc {return func(ctx *gin.Context) {ctx.HTML(http.StatusOK, "users/login.html", nil)}
}func LogoutGet() gin.HandlerFunc {return func(ctx *gin.Context) {session := sessions.Default(ctx)session.Delete(DefaultAuthInfoKey)session.Options(sessions.Options{Path:     "/",Domain:   "localhost",MaxAge:   0,Secure:   true,HttpOnly: false,SameSite: 0,})session.Save()ctx.Redirect(http.StatusFound, "/login")ctx.Abort()}
}func LoginPost() gin.HandlerFunc {return func(ctx *gin.Context) {username := ctx.PostForm("username")password := ctx.PostForm("password")if username != "admin" || password != "admin" {ctx.HTML(http.StatusOK, "users/login.html", gin.H{"Message": "用户名或密码错误!",})ctx.Abort()return}//登录成功auth := Auth{Username: username, Password: password}ctx.Set(DefaultAuthInfoKey, auth)session := sessions.Default(ctx)session.Set(DefaultAuthInfoKey, auth)session.Save() //TODO 必须Save,否则不生效ctx.Redirect(http.StatusFound, "/")}
}func Index() gin.HandlerFunc {return func(ctx *gin.Context) {ctx.HTML(http.StatusOK, "default/index.html", gin.H{"Content": "欢迎回来:" + ctx.MustGet(DefaultAuthInfoKey).(Auth).Username,})}
}

routers/router.go

package routersimport ("encoding/gob""github.com/coolbit/gin_sample/controllers""github.com/coolbit/gin_sample/middleware""github.com/gin-contrib/sessions""github.com/gin-contrib/sessions/cookie""github.com/gin-gonic/gin""net/http"
)var router *gin.Enginefunc GetRouter() *gin.Engine {return router
}func AuthRequired() gin.HandlerFunc {return func(ctx *gin.Context) {session := sessions.Default(ctx)auth := session.Get(controllers.DefaultAuthInfoKey)au, ok := auth.(controllers.Auth)if !ok || au.Username == "" {ctx.Redirect(http.StatusFound, "/login")ctx.Abort()return}ctx.Set(controllers.DefaultAuthInfoKey, auth) // 设置权限信息,供给当前请求链路使用session.Options(sessions.Options{             // 必须Save后才生效Path:     "/",Domain:   "localhost",MaxAge:   7 * 24 * 60 * 60, // 7天Secure:   true,HttpOnly: false,SameSite: 0,})session.Set(controllers.DefaultAuthInfoKey, au)session.Save() //"已刷新session"}
}func init() {router = gin.Default()// Set a lower memory limit for multipart forms (default is 32 MiB)router.MaxMultipartMemory = 8 << 20 // 8 MiBrouter.Static("/static", "static")router.LoadHTMLGlob("views/**/*")gob.Register(controllers.Auth{}) // TODO 这个必须有,没有就写不了cookiestore := cookie.NewStore([]byte("我是密钥"))router.Use(sessions.Sessions("SESSION_ID", store))router.GET("/login", controllers.LoginGet())router.POST("/login", controllers.LoginPost())router.Use(AuthRequired()) // 鉴权插件设置在这里router.GET("/", controllers.Index())
}

main.go

package mainimport ("github.com/coolbit/gin_sample/routers"
)func main() {routers.GetRouter().Run(":80")
}

登录后才能使用的系统的登录逻辑,借助cookie,session

  1. 客户端发起http://localhost/请求。
  2. 请求须经过后端AuthRequired中间件鉴权。该中间件查看session中是否保存了请求携带的cookie对应的用户信息,若有。则登录成功;若没有,则重定向到http://localhost/login进行登录。
  3. GET方法请求http://localhost/login时只返回页面,不需鉴权逻辑。
  4. POST方法请求http://localhost/login时,不需鉴权逻辑。进行登录验证,并记录session,为当前context设置Key为"AUTH"的有效用户信息。方便该次请求链路使用。登录成功则重定向到http://localhost/