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 controllers

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

package controllers

type Auth struct {
	Username string
	Password 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 routers

import (
	"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.Engine

func 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 MiB
	router.Static("/static", "static")
	router.LoadHTMLGlob("views/**/*")
	
	gob.Register(controllers.Auth{}) // TODO 这个必须有,没有就写不了cookie
	
	store := 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 main

import (
	"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/
  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
gin 是一种基于 Go 语言的 Web 框架,可以用来实现登录注册功能。以下是一个简单的示例代码: ```go package main import ( "github.com/gin-gonic/gin" "net/http" ) type User struct { Username string `json:"username"` Password string `json:"password"` } var users []User func main() { router := gin.Default() // 注册接口 router.POST("/register", func(c *gin.Context) { var user User if err := c.BindJSON(&user); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } for _, u := range users { if u.Username == user.Username { c.JSON(http.StatusBadRequest, gin.H{"error": "username already exists"}) return } } users = append(users, user) c.JSON(http.StatusOK, gin.H{"message": "register success"}) }) // 登录接口 router.POST("/login", func(c *gin.Context) { var user User if err := c.BindJSON(&user); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } for _, u := range users { if u.Username == user.Username && u.Password == user.Password { c.JSON(http.StatusOK, gin.H{"message": "login success"}) return } } c.JSON(http.StatusBadRequest, gin.H{"error": "username or password incorrect"}) }) router.Run(":808") } ``` 在这个示例中,我们定义了一个 `User` 结构体,包含用户名和密码两个字段。我们使用一个全局变量 `users` 来保存所有已注册的用户信息。 在注册接口中,我们首先通过 `BindJSON` 方法将请求体中的 JSON 数据绑定到 `user` 变量上。然后我们遍历已注册的用户列表,如果发现用户名已经存在,就返回错误信息。如果用户名不存在,就将新用户信息添加到 `users` 列表中,并返回注册成功的信息。 在登录接口中,我们也通过 `BindJSON` 方法将请求体中的 JSON 数据绑定到 `user` 变量上。然后我们遍历已注册的用户列表,如果发现用户名和密码都匹配,就返回登录成功的信息。如果用户名或密码不正确,就返回错误信息。 最后,我们使用 `router.Run` 方法启动 Web 服务器,监听 808 端口。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

metabit

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值