Gin教程使用JWT保护API

我正在学习使用Gin框架开发API,看到有文章提到可以用JWT进行API保护,但有几个问题不太明白:

  1. 在Gin中具体如何集成JWT验证?有没有完整的代码示例可以参考?
  2. JWT的密钥应该怎么生成和管理才比较安全?
  3. 如何设置合理的token过期时间?refresh token要怎么实现?
  4. 除了验证token有效性外,还需要做哪些安全措施来保护API?
  5. 有没有推荐的JWT库可以和Gin配合使用?

希望能得到一些实际项目中的经验分享,谢谢!

3 回复

要使用Gin和JWT保护API,首先安装依赖:go get -u github.com/dgrijalva/jwt-gogo get -u github.com/gin-gonic/gin

  1. 生成JWT Token
    用户登录时,创建包含用户信息的Token。例如:

    token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
        "id": userId,
        "exp": time.Now().Add(time.Hour * 24).Unix(),
    })
    tokenString, _ := token.SignedString([]byte("your-secret-key"))
    
  2. 中间件验证Token
    创建一个JWT验证中间件:

    func JWTMiddleware() gin.HandlerFunc {
        return func(c *gin.Context) {
            tokenStr := c.GetHeader("Authorization")
            if tokenStr == "" {
                c.JSON(401, gin.H{"error": "未提供token"})
                c.Abort()
                return
            }
            token, err := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) {
                return []byte("your-secret-key"), nil
            })
            if err != nil || !token.Valid {
                c.JSON(401, gin.H{"error": "无效的token"})
                c.Abort()
                return
            }
            c.Next()
        }
    }
    
  3. 应用到路由
    将中间件应用到需要保护的路由:

    r := gin.Default()
    r.POST("/login", loginHandler)
    r.GET("/protected", JWTMiddleware(), protectedHandler)
    r.Run(":8080")
    

这样,所有访问/protected的请求都需要携带有效的JWT Token。


Gin框架搭配JWT(JSON Web Token)可以很好地保护API。首先安装依赖gin-jwtjwt-go

  1. 初始化Gin路由:
package main

import (
    "github.com/gin-gonic/gin"
    jwtmiddleware "github.com/appleboy/gin-jwt/v2"
)

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

    authMiddleware, _ := jwtmiddleware.New(&jwtmiddleware.Config{
        Secret: []byte("your-secret-key"),
        SigningMethod: "HS256",
        TokenLookup: "header: Authorization",
        KeyFunc: func(c *jwtmiddleware.Context) interface{} {
            return []byte("your-secret-key")
        },
    })

    r.POST("/login", authMiddleware.LoginHandler)
    r.NoRoute(authMiddleware.MiddlewareFunc(), func(c *gin.Context) {
        claims := jwtmiddleware.ExtractClaims(c)
        c.JSON(200, claims)
    })
    r.Run(":8080")
}
  1. 用户登录时生成JWT:
r.POST("/login", authMiddleware.LoginHandler, func(c *gin.Context) {
    c.JSON(200, gin.H{"msg": "You are already logged in"})
})
  1. 在受保护的API上使用JWT:
r.GET("/protected", authMiddleware.MiddlewareFunc(), func(c *gin.Context) {
    claims := jwtmiddleware.ExtractClaims(c)
    c.JSON(200, gin.H{"message": "Hello protected route", "claims": claims})
})

启动服务后,用户先通过/login接口获取JWT,然后在请求头中携带Authorization: Bearer <token>访问受保护的API。

Gin框架中使用JWT保护API教程

JWT(JSON Web Token)是一种流行的API认证方式,下面介绍如何在Gin框架中使用JWT保护API。

1. 安装所需库

go get github.com/gin-gonic/gin
go get github.com/dgrijalva/jwt-go

2. 基本实现代码

package main

import (
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

// 自定义Claims结构
type CustomClaims struct {
	UserID string `json:"user_id"`
	jwt.StandardClaims
}

var jwtKey = []byte("your_secret_key")

// 生成JWT
func GenerateToken(userID string) (string, error) {
	claims := CustomClaims{
		UserID: userID,
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: time.Now().Add(time.Hour * 24).Unix(),
			Issuer:    "your_app_name",
		},
	}

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

// JWT验证中间件
func AuthMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		tokenString := c.GetHeader("Authorization")
		if tokenString == "" {
			c.JSON(http.StatusUnauthorized, gin.H{"error": "未提供认证令牌"})
			c.Abort()
			return
		}

		claims := &CustomClaims{}
		token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
			return jwtKey, nil
		})

		if err != nil || !token.Valid {
			c.JSON(http.StatusUnauthorized, gin.H{"error": "无效的认证令牌"})
			c.Abort()
			return
		}

		c.Set("userID", claims.UserID)
		c.Next()
	}
}

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

	// 登录路由
	r.POST("/login", func(c *gin.Context) {
		// 验证用户凭据...
		// 假设验证成功
		token, err := GenerateToken("123456")
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "无法生成令牌"})
			return
		}
		c.JSON(http.StatusOK, gin.H{"token": token})
	})

	// 受保护的路由
	api := r.Group("/api")
	api.Use(AuthMiddleware())
	{
		api.GET("/protected", func(c *gin.Context) {
			userID := c.MustGet("userID").(string)
			c.JSON(http.StatusOK, gin.H{"message": "访问受保护资源成功", "user_id": userID})
		})
	}

	r.Run(":8080")
}

3. 使用说明

  1. 客户端首先调用/login获取JWT令牌
  2. 之后在访问受保护API时,需要在请求头中添加:
    Authorization: <your_token>
    
  3. 服务器会验证令牌的有效性,无效则返回401错误

4. 安全建议

  1. 使用强密钥并定期更换
  2. 设置合理的令牌过期时间
  3. 考虑使用HTTPS传输
  4. 敏感操作可要求重新验证

这就是在Gin框架中使用JWT保护API的基本方法。根据实际需求,你可以进一步扩展和优化这个实现。

回到顶部