gin+jwt验证,cookie

cookie示范

//设置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:

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:

// 文章内容
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)
}

需要验证身份的路由:

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

验证身份的视图函数:

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