gin框架jwt认证
middlewares/authmiddleware.go
// 导入必要的包
package middlewares
import (
"net/http" // HTTP 状态码和常量
"time" // 时间操作,用于设置 token 过期时间
"github.com/gin-gonic/gin" // Web 框架
"github.com/golang-jwt/jwt/v5" // JWT 库
)
// 定义 JWT 签名密钥(生产环境应使用环境变量)
var jwtSecret = []byte("qweasdzxc")
// 自定义 JWT 声明结构体
type Claims struct {
Username string `json:"username"` // 用户名,将存储在 token 中
jwt.RegisteredClaims // 嵌入标准声明(过期时间、发布时间等)
}
// 生成 JWT token 的函数
func GenerateToken(username string) (string, error) {
// 创建声明对象
claims := Claims{
Username: username,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)), // 设置过期时间:24小时后
IssuedAt: jwt.NewNumericDate(time.Now()), // 设置发布时间:当前时间
},
}
// 使用 HS256 算法和声明创建 token
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// 使用密钥签名并返回 token 字符串
return token.SignedString(jwtSecret)
}
// 认证中间件函数
func AuthMiddleware() gin.HandlerFunc {
// 返回一个 gin.HandlerFunc(中间件函数)
return func(c *gin.Context) {
// 从请求头中获取 Authorization 字段
tokenString := c.GetHeader("Authorization")
// 如果 token 为空,返回 401 未授权错误
if tokenString == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "缺少授权 token"})
c.Abort() // 终止请求处理
return
}
// 移除 "Bearer " 前缀(如果存在)
if len(tokenString) > 7 && tokenString[:7] == "Bearer " {
tokenString = tokenString[7:] // 截取第 7 个字符之后的部分
}
// 解析并验证 token
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
return jwtSecret, nil // 返回密钥用于验证签名
})
// 如果解析出错或 token 无效,返回 401 错误
if err != nil || !token.Valid {
c.JSON(http.StatusUnauthorized, gin.H{"error": "无效的 token"})
c.Abort() // 终止请求
return
}
// 尝试将 token 的声明转换为 Claims 类型
if claims, ok := token.Claims.(*Claims); ok {
// 将用户名存入上下文,供后续处理器使用
c.Set("username", claims.Username)
c.Next() // 继续处理下一个中间件或处理器
} else {
// 类型转换失败,返回错误
c.JSON(http.StatusUnauthorized, gin.H{"error": "无效的 token claims"})
c.Abort() // 终止请求
}
}
}
main.go
package main
import (
"fmt"
"gojwt/middlewares"
"gojwt/routers"
"net/http"
"log"
"github.com/gin-gonic/gin"
)
func FaultError(err error, error string) {
if err != nil {
log.Printf("%s: %v", error, err)
}
}
func initMiddleware(ctx *gin.Context) {
fmt.Println("我是一个中间件")
ctx.Next()
}
func main() {
r := gin.Default()
r.Use(initMiddleware)
// r.Use(middlewares.AuthMiddleware())
routers.ApiRouterInit(r)
r.GET("/", middlewares.AuthMiddleware(), func(ctx *gin.Context) {
value, _ := ctx.Get("username")
ctx.JSON(200, gin.H{
"message": "ok",
"user": value,
})
})
r.POST("/login", func(c *gin.Context) {
// 定义匿名结构体接收 JSON 数据
var credentials struct {
Username string `json:"username"`
Password string `json:"password"`
}
// 绑定 JSON 数据到结构体
if err := c.BindJSON(&credentials); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// 验证凭证(实际项目中应查询数据库)
if credentials.Username == "admin" && credentials.Password == "password" {
// 验证成功,生成 token(忽略错误)
token, _ := middlewares.GenerateToken(credentials.Username)
// 返回 token 给客户端
c.JSON(http.StatusOK, gin.H{"token": token})
} else {
// 验证失败,返回 401 错误
c.JSON(http.StatusUnauthorized, gin.H{"error": "无效的凭证"})
}
})
r.Run()
}

浙公网安备 33010602011771号