gin+jwt验证,cookie


cookie示范

go
//设置cookie
//字段名,内容,有效期(秒),生效路径,有效域,仅https,仅HTTP访问Cookie(js无法访问)
c.SetCookie("token", tokenString, 680400, "/", "127.0.0.1", false, true)

//读取cookie
tokenString, _ := c.Cookie("token")

// 如果没有 token 字段,返回 401 错误
if tokenString == "" {
	c.JSON(401, gin.H{"error": "未提供身份验证信息"})
	c.Abort()
	return
}

jwt示范

jwt.go:

go
package services

import (
	"github.com/golang-jwt/jwt/v5"
	"github.com/gin-gonic/gin"
	"time"
	"fmt"
)

// 定义 JWT 签名密钥
var jwtKey = []byte("1sD5e+cF2rNeP7Mt6_k3R7e4y")


// 定义 JWT 签发函数
func GenerateJWT(user string) (string, error) {
	// 创建 JWT Claims 对象
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		//设置超时时间
		"exp": time.Now().Add(10080 * time.Minute).Unix(),
		"username":   "muxiaoliang", //这是存入的用户名
	})
	// 生成 JWT Token
	tokenString, err := token.SignedString(jwtKey)
	// 使用密钥进行签名生成字符串 token
	if err != nil {
		return "", err
	}
	return tokenString, nil
}

// 定义 JWT 认证中间件函数
func AuthenticateJWT(c *gin.Context) {
	// // 获取请求头中的 Authorization 字段
	// tokenString := c.GetHeader("Authorization")
	//获取cookie中的token字段
	tokenString, _ := c.Cookie("token")

	// 如果没有 Authorization 字段,返回 401 错误
	if tokenString == "" {
		c.JSON(401, gin.H{"error": "未提供身份验证信息"})
		c.Abort()
		return
	}

	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		//这里的参数就是方法,方法直接返回jwtKey令牌
		return jwtKey, nil
	})

	// 检查token是否有效
    if !token.Valid {
        c.JSON(401, gin.H{"无效的token": err})
		fmt.Println("无效的token",err)
		c.Abort()
        return
    }
	if claims, ok := token.Claims.(jwt.MapClaims); ok {
		fmt.Println("找到用户:", claims["username"])
		// 将解析后的claims存储到上下文中,以便后续处理程序可以访问
		//例如返回用户名,权限
		c.Set("claims", claims["username"])
	} else {
		fmt.Println("token解析失败",err)
		c.JSON(401, gin.H{"token解析失败": err})
		c.Abort()
        return
	}
	c.Next()
}

user.go:

go
// 文章内容
func User(c *gin.Context) {
	// 获取当前请求的HTTP方法
	method := c.Request.Method
	//如果是post
	if method == "POST" {
		//登录验证
		user := c.PostForm("username")
		password := c.PostForm("password")

		//这里是验证用户密码逻辑,假如已经验证通过
		
		//调用jwt签发函数并保存到cookie,也可以直接返回json的token让客户端自己处理
		tokenString, err := services.GenerateJWT(user)
		if err != nil {
			c.JSON(400, gin.H{"error": "生成令牌失败"})
			return
		}
		c.SetCookie("token", tokenString, 680400, "/", "127.0.0.1", false, true)
		//跳转到后台路由
		c.Redirect(302, "/admin")
		return
	}
	//如果是get方法则直接返回页面
	c.HTML(200, "user.html", nil)
}

需要验证身份的路由:

go
//services.AuthenticateJWT是中间函数,controller.Admin是视图函数
//路由会依此执行下面的函数
r.GET("/admin",services.AuthenticateJWT,controller.Admin)  //管理员页面,需要验证

验证身份的视图函数:

go
// 管理员页面
func Admin(c *gin.Context) {
	// // 获取上下文传递的内容,例如用户名,权限
	// claims := c.MustGet("claims")
	c.HTML(200, "admin_index.html",nil)
}

愿意放弃自由来换取保障的人,他最终既得不到自由,也得不到保障 -- 哈耶克