go get -u github.com/gin-gonic/gin
go get -u github.com/dgrijalva/jwt-go
package main
import (
"net/http"
"time"
"github.com/gin-gonic/gin"
"github.com/dgrijalva/jwt-go"
)
var (
jwtKey =
[]byte("your_secret_key")
)
// Claims 结构定义
type Claims struct {
Username string
`json:"username"`
jwt.StandardClaims
}
func main() {
router :=
gin.Default()
// 登录端点,用于获取JWT
Token
router.POST("/login",
loginHandler)
//
使用JWT中间件保护需要验证的端点
auth :=
router.Group("/auth")
auth.Use(authMiddleware())
{
auth.GET("/data", dataHandler)
}
router.Run(":8080")
}
// 处理登录,生成JWT Token
func loginHandler(c *gin.Context) {
var loginVals struct
{
Username string `json:"username"`
Password string `json:"password"`
}
if err :=
c.ShouldBindJSON(&loginVals); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error":
"Invalid login details"})
return
}
//
实际情况下,这里应该验证用户名和密码
// 生成JWT Token
expirationTime :=
time.Now().Add(5 * time.Minute)
claims :=
&Claims{
Username: loginVals.Username,
StandardClaims: jwt.StandardClaims{
ExpiresAt:
expirationTime.Unix(),
},
}
token :=
jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err :=
token.SignedString(jwtKey)
if err != nil {
c.JSON(http.StatusInternalServerError,
gin.H{"error": "Failed to generate token"})
return
}
c.JSON(http.StatusOK,
gin.H{"token": tokenString})
}
// JWT 验证中间件
func authMiddleware() gin.HandlerFunc {
return func(c
*gin.Context) {
tokenString :=
c.GetHeader("Authorization")
if tokenString == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Authorization
header required"})
c.Abort()
return
}
token, err := jwt.ParseWithClaims(tokenString,
&Claims{}, func(token *jwt.Token) (interface{}, error) {
return
jwtKey, nil
})
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid
token"})
c.Abort()
return
}
if !token.Valid {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid
token"})
c.Abort()
return
}
// 将claims信息存储在上下文中,供后续请求处理函数使用
claims, ok := token.Claims.(*Claims)
if !ok {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Failed to parse
claims from token"})
c.Abort()
return
}
c.Set("username", claims.Username)
c.Next()
}
}
// 受保护的数据端点
func dataHandler(c *gin.Context) {
username :=
c.GetString("username")
c.JSON(http.StatusOK,
gin.H{"data": "protected data for " + username})
}
加载中,请稍候......