golang 中 Jwt 的验证及续期使用
创建Utils的Jwt文件,用于创建Jwt Token 和 验证并继期
package utils import ( "errors" "fmt" "github.com/dgrijalva/jwt-go" "strings" "time" ) // 生成Jwt Token // @Param secretKey 表示jwt secretKey【*******注意:发布多台时secretKey 必须一样*********】 // @Result string 创建的Token // @Result error 返回验证错误信息 func GenerateJWTToken() (string, error) { // secretKey 表示jwt 的secretKey【*******注意:发布多台时secretKey 必须一样,否则通不过验证*********】 // 获取 ini 文件配置的 Jwt SecretKey var secretKey = GetIniVale("jwt", "SecretKey") claims := jwt.MapClaims{ "sub": "1234567890", "name": "John Doe", "iat": time.Now().Unix(), "exp": time.Now().Add(time.Minute * 3).Unix(), } // 使用指定的签名方法和密钥创建令牌 token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) tokenString, err := token.SignedString([]byte(secretKey)) if err != nil { return "", err } return tokenString, nil } // 验证Jwt token 并且如果Token快过期,就创建新的token // @Param tokenString 表示jwt token // @Result bool 验证是否通过 // @Result string 快过期创建新的Token,没有则为空 // @Result error 返回验证错误信息 func ValidateJWTToken(tokenString string) (bool, string, error) { // secretKey 表示jwt 的secretKey【*******注意:发布多台时secretKey 必须一样,否则通不过验证*********】 // 获取 ini 文件配置的 Jwt SecretKey var secretKey = GetIniVale("jwt", "SecretKey") tokenString = strings.TrimPrefix(tokenString, "Bearer ") token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { return []byte(secretKey), nil }) if err != nil { return false, "", err } claims, ok := token.Claims.(jwt.MapClaims) // token 验证 if ok && token.Valid { // Token是否过期 if !claims.VerifyExpiresAt(time.Now().Unix(), false) { return false, "", errors.New("access token expired") } // 一分钟过期就重新添加一个Token 返回给前端 if !claims.VerifyExpiresAt(time.Now().Add(time.Minute).Unix(), false) { newToken, _ := GenerateJWTToken() return true, newToken, nil } return true, "", nil } else { return false, "", fmt.Errorf("Invalid token") } }
编写登录创建jwt token
package controller import ( "github.com/gin-gonic/gin" "jwt/utils" ) type UserController struct{} func (u UserController) Login(c *gin.Context) { userName := c.Query("userName") pwd := c.Query("password") if userName == "zs" && pwd == "123" { // 登录成功 生成Jwt Token token, err := utils.GenerateJWTToken() if err != nil { c.JSON(500, gin.H{"Msg": "生成Token失败:" + err.Error()}) } else { c.JSON(200, gin.H{"Token": token}) } } else { c.JSON(500, gin.H{"Msg": "用户中或密码错误!"}) } }
在gin 中 添加中间件,用于验证 token
package middleware import ( "github.com/gin-gonic/gin" "jwt/utils" "strings" ) func ValidataToken() gin.HandlerFunc { return func(c *gin.Context) { // 判断 是不是登录链接,如果是直接往下走 if strings.Contains(strings.ToLower(c.Request.RequestURI), "/user/login") { c.Next() } else { token := c.GetHeader("Authorization") // 验证token 并且如果 Token快过期 就创建新的token bls, newToken, err := utils.ValidateJWTToken(token) if err != nil { c.JSON(500, gin.H{ "msg": err.Error(), }) c.Abort() return } else { if bls { // 是否有快过期创建新的Token if len(newToken) > 0 { c.Header("newToken", newToken) // 将新Token添加到返回的Header里,方便前端使用 } c.Next() } else { c.JSON(401, gin.H{"msg": "token not validated"}) c.Abort() return } } } } }
gin 中use中间件
package main import ( "github.com/gin-gonic/gin" "jwt/middleware" "jwt/route" ) func main() { r := gin.Default() r.Use(middleware.ValidataToken()) route.AddUserInfoRoute(r) r.Run(":8080") }