news 2026/5/11 12:20:13

go jwt

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
go jwt

我来为你详细介绍在 Go 语言中使用 JWT 的实践方案。

Go 语言 JWT 库推荐

Go 生态中最流行的 JWT 库是 `github.com/golang-jwt/jwt/v5`(原 `dgrijalva/jwt-go` 的社区维护分支,更安全可靠)。

快速开始

1. 安装依赖

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

2. 基础使用示例

生成 Token(登录时)

```go
package main

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

// 定义密钥(生产环境应从环境变量读取)
var jwtSecret = []byte("your-256-bit-secret")

// 自定义 Claims 结构
type UserClaims struct {
UserID uint `json:"user_id"`
Username string `json:"username"`
jwt.RegisteredClaims // 内嵌标准声明
}

// 生成 JWT
func GenerateToken(userID uint, username string) (string, error) {
claims := UserClaims{
UserID: userID,
Username: username,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)), // 24小时过期
IssuedAt: jwt.NewNumericDate(time.Now()),
Subject: "user_token",
},
}

token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString(jwtSecret)
}
```

解析和验证 Token(中间件中)

```go
// 解析 JWT
func ParseToken(tokenString string) (*UserClaims, error) {
token, err := jwt.ParseWithClaims(tokenString, &UserClaims{}, func(token *jwt.Token) (interface{}, error) {
// 验证签名算法
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, jwt.ErrSignatureInvalid
}
return jwtSecret, nil
})

if err != nil {
return nil, err
}

if claims, ok := token.Claims.(*UserClaims); ok && token.Valid {
return claims, nil
}
return nil, jwt.ErrInvalidKey
}
```

Gin 框架集成示例

这是实际项目中最常见的使用场景:

```go
package main

import (
"net/http"
"strings"
"time"

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

var jwtSecret = []byte("your-secret-key")

// JWT 中间件
func JWTAuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
authHeader := c.GetHeader("Authorization")
if authHeader == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "缺少认证头"})
c.Abort()
return
}

// 提取 Bearer token
parts := strings.SplitN(authHeader, " ", 2)
if !(len(parts) == 2 && parts[0] == "Bearer") {
c.JSON(http.StatusUnauthorized, gin.H{"error": "认证头格式错误"})
c.Abort()
return
}

// 解析 token
claims, err := ParseToken(parts[1])
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "无效的token"})
c.Abort()
return
}

// 将用户信息存入上下文
c.Set("userID", claims.UserID)
c.Set("username", claims.Username)
c.Next()
}
}

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

// 公开路由
r.POST("/login", loginHandler)

// 需要认证的路由组
api := r.Group("/api")
api.Use(JWTAuthMiddleware())
{
api.GET("/profile", profileHandler)
api.POST("/logout", logoutHandler)
}

r.Run(":8080")
}

// 登录处理
func loginHandler(c *gin.Context) {
var req struct {
Username string `json:"username"`
Password string `json:"password"`
}

if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

// 验证用户名密码(示例,实际应查数据库)
if req.Username != "admin" || req.Password != "123456" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "认证失败"})
return
}

// 生成 token
token, err := GenerateToken(1, req.Username)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "生成token失败"})
return
}

c.JSON(http.StatusOK, gin.H{
"token": token,
"type": "Bearer",
})
}

// 获取个人信息(需要认证)
func profileHandler(c *gin.Context) {
userID, _ := c.Get("userID")
username, _ := c.Get("username")

c.JSON(http.StatusOK, gin.H{
"user_id": userID,
"username": username,
})
}
```

高级特性

使用 RSA 非对称加密(更安全的微服务场景)

```go
// 生成 Token(使用私钥)
func GenerateTokenWithRSA(userID uint, privateKey *rsa.PrivateKey) (string, error) {
claims := jwt.MapClaims{
"user_id": userID,
"exp": time.Now().Add(time.Hour * 24).Unix(),
}

token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
return token.SignedString(privateKey)
}

// 验证 Token(使用公钥)
func ParseTokenWithRSA(tokenString string, publicKey *rsa.PublicKey) (*jwt.Token, error) {
return jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return publicKey, nil
})
}
```

Token 刷新机制

```go
// RefreshToken 在 token 即将过期时生成新 token
func RefreshToken(tokenString string) (string, error) {
claims, err := ParseToken(tokenString)
if err != nil {
return "", err
}

// 检查是否需要刷新(例如剩余时间小于30分钟)
if time.Until(claims.ExpiresAt.Time) > 30*time.Minute {
return "", errors.New("token 尚未需要刷新")
}

// 生成新 token
return GenerateToken(claims.UserID, claims.Username)
}
```

目录结构建议

```
project/
├── internal/
│ ├── middleware/
│ │ └── jwt.go # JWT 中间件
│ └── utils/
│ └── jwt.go # JWT 工具函数
├── pkg/
│ └── config/
│ └── config.go # 密钥配置
└── cmd/
└── server/
└── main.go
```

安全最佳实践

实践 说明
密钥管理 使用环境变量或密钥管理服务(KMS),不要硬编码
算法选择 优先使用 `HS256` 或 `RS256`,避免 `none` 算法
过期时间 设置合理的过期时间(建议 15分钟-2小时)
HTTPS 传输 生产环境必须使用 HTTPS
Token 存储 前端存储在 `httpOnly` Cookie 或内存中,避免 LocalStorage XSS 风险

需要了解更具体的场景实现(如 Redis 存储黑名单实现登出、多设备登录控制等)吗?

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/10 5:11:28

1966-2025年低空经济企业数据库

低空经济通常指围绕“低空空域”的飞行活动及其配套产业形成的综合经济形态。它以各类航空器的低空飞行应用为牵引,向上游制造、向下游运营服务与治理体系延展,形成“制造—运营—服务—基础设施—监管保障”的产业链 团队参考李牧南(2024&a…

作者头像 李华
网站建设 2026/5/9 4:50:23

基于Java的彩灯加工智慧管理系统的设计与实现全方位解析:附毕设论文+源代码

1. 为什么这个毕设项目值得你 pick ? 毕设不用从零敲!基于Java的彩灯加工智慧管理系统的设计与实现。该系统主要功能模块包括供应商管理、加工单位管理、产品管理、业务登记管理、交货单管理和供应商付款管理,满足普通员工和部门领导的数据录入查阅执行…

作者头像 李华
网站建设 2026/5/9 6:04:07

基于Java的影视剪辑智慧管理系统的设计与实现全方位解析:附毕设论文+源代码

1. 为什么这个毕设项目值得你 pick ? 基于Java的影视剪辑智慧管理系统的设计与实现,提供了一种针对传统选题的优势、创新性和实用性的摆脱方案。该系统主要功能模块包括会员管理、视频管理、素材及任务日志等多个子系统,覆盖了从用户数据录入到项目导出…

作者头像 李华
网站建设 2026/5/2 21:58:59

强烈安利 10个降AIGC工具:专科生降AI率全攻略

在如今的学术写作中,AI 生成内容(AIGC)已经成为一个不可忽视的现象。对于专科生来说,论文写作不仅需要满足学术规范,还要避免被检测出 AI 生成痕迹,以免影响成绩或遭遇查重风险。这时候,AI 降重…

作者头像 李华