一、什么是 JWT

JWT(JSON Web Token)是一种轻量级认证方案,用于:

  • 前后端分离的用户认证
  • 传递安全信息

特点:

  • 无状态(服务端不存储 Session)
  • 可跨域、可跨服务
  • 支持加密或签名

JWT 本质上是一个字符串,由三部分组成:

header.payload.signature

二、JWT 三部分详解

1. Header(头部)

  • 声明类型和加密算法
  • 通常是:
{
  "alg": "HS256",
  "typ": "JWT"
}

2. Payload(负载)

  • 存储实际信息(Claims)
  • 比如用户 ID、过期时间等
{
  "userId": 1001,
  "username": "zjl",
  "exp": 1684089600
}
  • exp 表示过期时间(Unix 时间戳)

3. Signature(签名)

签名算法:

HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)

作用:

防篡改,确保 JWT 没有被伪造


三、JWT 优势

  • 无需服务器存储 Session
  • 支持跨域和微服务
  • 适合前后端分离场景

四、Go 中使用 JWT

Go 常用库:

github.com/golang-jwt/jwt/v4

安装:

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

五、生成 JWT

示例代码:

package main

import (
	"fmt"
	"time"

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

func main() {
	// 声明 payload
	claims := jwt.MapClaims{
		"userId":   1001,
		"username": "zjl",
		"exp":      time.Now().Add(time.Hour * 1).Unix(),
	}

	// 创建 token
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

	// 使用 secret 签名
	secret := []byte("mysecret")
	tokenString, err := token.SignedString(secret)
	if err != nil {
		panic(err)
	}

	fmt.Println("生成的 JWT:", tokenString)
}

六、解析 JWT

package main

import (
	"fmt"

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

func main() {
	tokenString := "上一步生成的 token"

	secret := []byte("mysecret")

	// 解析 token
	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		return secret, nil
	})

	if err != nil {
		panic(err)
	}

	// 校验通过
	if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
		fmt.Println("userId:", claims["userId"])
		fmt.Println("username:", claims["username"])
	} else {
		fmt.Println("Token 无效")
	}
}

七、JWT 在 Gin 中使用

1. 登录接口生成 token

r.POST("/login", func(c *gin.Context) {
	// 假设校验用户名密码通过
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"userId": 1001,
		"exp":    time.Now().Add(time.Hour * 1).Unix(),
	})

	tokenString, _ := token.SignedString([]byte("mysecret"))

	c.JSON(200, gin.H{
		"token": tokenString,
	})
})

2. 中间件校验 JWT

func JWTMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		tokenString := c.GetHeader("Authorization")
		if tokenString == "" {
			c.JSON(401, gin.H{"msg": "缺少 token"})
			c.Abort()
			return
		}

		token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
			return []byte("mysecret"), nil
		})

		if err != nil || !token.Valid {
			c.JSON(401, gin.H{"msg": "token 无效"})
			c.Abort()
			return
		}

		c.Next()
	}
}

使用:

auth := r.Group("/auth")
auth.Use(JWTMiddleware())
auth.GET("/profile", func(c *gin.Context) {
	c.JSON(200, gin.H{"msg": "这是受保护的接口"})
})

八、JWT 注意事项

  1. Secret 必须保密
  2. token 应该设置过期时间
  3. 不要在 payload 放敏感信息(密码等)
  4. 前端使用 Authorization: Bearer token 传递

九、总结

JWT 核心概念:

  1. Header:声明算法和类型
  2. Payload:存放用户信息和过期时间
  3. Signature:签名,防篡改

在 Go Web 开发中:

  • 登录生成 JWT
  • 前端存储 token
  • 请求带 token
  • 后端中间件验证 token

这样就完成了无状态认证。


Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐