🏷️ 标签:Gin Go JWT 登录认证 Token 中间件 后端开发 📝 适用人群:Go 初学者、Gin 开发者、前后端分离、课程实训、CSDN 发布 💡 亮点:企业级标准方案,通俗易懂、完整可运行、包含登录颁发 Token、接口鉴权、中间件拦截、Token 过期处理,直接用于项目。


一、前言

在前后端分离项目中,JWT(JSON Web Token) 是目前最主流、最通用的登录认证方案。 相比传统 Session,JWT 无需存储在服务器、支持跨域、适合分布式部署,是现代 Web 开发必备技能。

本文带你从零彻底学会:

  1. JWT 原理与结构
  2. Gin 集成 JWT 库
  3. 登录接口 → 生成并返回 Token
  4. JWT 认证中间件 → 拦截未登录请求
  5. Token 过期、无效、伪造异常处理
  6. 实战可用的完整代码

二、什么是 JWT?

2.1 JWT 是什么

JWT = JSON Web Token 一段加密后的字符串,用于在网络应用中声明身份

特点:

  • 服务端不存储会话(无状态)
  • 自带用户信息,加密安全
  • 支持跨域、分布式、微服务
  • 前后端分离标配

2.2 JWT 组成结构

一段 Token 分为三部分:

  1. Header(头部):加密算法
  2. Payload(负载):存放用户 ID、用户名、过期时间
  3. Signature(签名):防篡改

最终长成这样:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsInVzZXJuYW1lIjoiYWRtaW4iLCJleHAiOjE3MzAwMDAwMDB9.xxxxxx

2.3 JWT 认证流程

  1. 用户登录 → 账号密码正确
  2. 服务端生成 JWT Token → 返回给前端
  3. 前端存储 Token(localStorage)
  4. 后续请求在请求头携带:Authorization: Bearer Token
  5. 服务端验证 Token 有效 → 放行请求

三、环境准备

3.1 安装 JWT 依赖

go get github.com/golang-jwt/jwt/v5

3.2 基础项目结构

项目/
├── main.go          # 主入口
├── utils/
│   └── jwt.go       # JWT工具类
└── middleware/
    └── jwt_auth.go  # JWT认证中间件

四、编写 JWT 工具类(核心)

创建 utils/jwt.go,用于生成 Token解析 Token

package utils

import (
	"errors"
	"time"

	"github.com/golang-jwt/jwt/v5"
)

// 密钥(一定要自己改!)
var jwtKey = []byte("my_secret_key_123456789")

// 自定义Claims(存放要加密的用户信息)
type MyClaims struct {
	UserId   int    `json:"userId"`
	Username string `json:"username"`
	jwt.RegisteredClaims
}

// 生成Token
func GenerateToken(userId int, username string) (string, error) {
	// 1. 创建自定义声明
	claims := MyClaims{
		UserId:   userId,
		Username: username,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)), // 过期时间24小时
			IssuedAt:  jwt.NewNumericDate(time.Now()),                    // 签发时间
		},
	}

	// 2. 使用HS256加密生成token
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

	// 3. 签名
	return token.SignedString(jwtKey)
}

// 解析Token
func ParseToken(tokenString string) (*MyClaims, error) {
	// 解析token
	token, err := jwt.ParseWithClaims(tokenString, &MyClaims{}, func(token *jwt.Token) (interface{}, error) {
		return jwtKey, nil
	})

	if err != nil {
		return nil, err
	}

	// 校验token
	if claims, ok := token.Claims.(*MyClaims); ok && token.Valid {
		return claims, nil
	}

	return nil, errors.New("无效的token")
}

五、编写 JWT 认证中间件

创建 middleware/jwt_auth.go,用于拦截未登录请求

package middleware

import (
	"strings"

	"github.com/gin-gonic/gin"
	"your-project/utils"
)

// JWT认证中间件
func JWTAuthMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 1. 获取请求头Authorization
		authHeader := c.GetHeader("Authorization")
		if authHeader == "" {
			c.JSON(401, gin.H{"code": 401, "msg": "未携带Token,拒绝访问"})
			c.Abort()
			return
		}

		// 2. 按格式 Bearer token 切割
		parts := strings.SplitN(authHeader, " ", 2)
		if !(len(parts) == 2 && parts[0] == "Bearer") {
			c.JSON(401, gin.H{"code": 401, "msg": "Token格式错误"})
			c.Abort()
			return
		}

		// 3. 解析Token
		claims, err := utils.ParseToken(parts[1])
		if err != nil {
			c.JSON(401, gin.H{"code": 401, "msg": "Token无效或已过期"})
			c.Abort()
			return
		}

		// 4. 将用户信息存入上下文,后续接口可直接使用
		c.Set("userId", claims.UserId)
		c.Set("username", claims.Username)

		// 5. 放行
		c.Next()
	}
}

六、主程序:登录接口 + 测试接口

main.go

package main

import (
	"github.com/gin-gonic/gin"
	"your-project/middleware"
	"your-project/utils"
)

func main() {
	r := gin.Default()

	// 公共路由(无需登录)
	r.POST("/login", func(c *gin.Context) {
		// 1. 获取前端传的账号密码
		username := c.PostForm("username")
		password := c.PostForm("password")

		// 2. 模拟校验(真实项目查数据库)
		if username == "admin" && password == "123456" {
			// 3. 生成Token
			token, _ := utils.GenerateToken(1, username)
			c.JSON(200, gin.H{
				"code": 200,
				"msg":  "登录成功",
				"token": token,
			})
			return
		}

		c.JSON(200, gin.H{"code": 400, "msg": "账号或密码错误"})
	})

	// 需要登录认证的路由组
	authGroup := r.Group("/api")
	authGroup.Use(middleware.JWTAuthMiddleware())
	{
		// 获取用户信息
		authGroup.GET("/user/info", func(c *gin.Context) {
			userId, _ := c.Get("userId")
			username, _ := c.Get("username")
			c.JSON(200, gin.H{
				"userId":   userId,
				"username": username,
			})
		})
	}

	r.Run(":8080")
}

七、接口测试

1. 登录接口(获取 Token)

POST http://localhost:8080/login
参数:
username=admin
password=123456

返回:

{
  "code": 200,
  "msg": "登录成功",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

2. 带 Token 请求需要登录的接口

请求头:

Authorization: Bearer 你的Token

接口地址:

GET http://localhost:8080/api/user/info

返回用户信息,说明认证成功


八、JWT 常见异常说明

异常场景 提示
未传 Token 未携带 Token,拒绝访问
格式错误 Token 格式错误
过期 / 伪造 Token 无效或已过期
正确 成功获取用户信息

九、JWT 优点总结

  1. 无状态:服务端不用存储 Session,减轻压力
  2. 跨域完美支持:不受 Cookie 跨域限制
  3. 分布式友好:多台服务器共享认证
  4. 自包含:自带用户信息,无需查库
  5. 安全:签名防篡改,加密传输

十、企业级注意事项

  1. jwtKey 密钥必须复杂、不能泄露
  2. Token 过期时间不宜过长(2 小时~1 天)
  3. 敏感信息不要放在 Payload(可解码)
  4. 生产环境建议使用 HTTPS
  5. 可实现 RefreshToken 机制,自动续期

十一、总结

  1. JWT 是前后端分离标准登录方案
  2. 流程:登录生成 Token → 请求携带 Token → 中间件验证
  3. 核心三部分:工具类(生成 / 解析)、认证中间件、登录接口
  4. Gin 中使用 github.com/golang-jwt/jwt/v5
  5. 中间件拦截未登录请求,安全可靠
  6. 无状态、跨域、分布式支持,企业必用

版权声明

本文为原创 Gin JWT 登录认证 实战教程,代码完整可直接运行,适合 CSDN 发布、课程实训、作业、面试复习,禁止未经授权转载抄袭。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐