创建Utils的Jwt文件,用于创建Jwt Token 和 验证并继期
package utilsimport ("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 SecretKeyvar 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 SecretKeyvar 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 controllerimport ("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 Tokentoken, 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 middlewareimport ("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快过期 就创建新的tokenbls, newToken, err := utils.ValidateJWTToken(token)if err != nil {c.JSON(500, gin.H{"msg": err.Error(),})c.Abort()return} else {if bls {// 是否有快过期创建新的Tokenif 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 mainimport ("github.com/gin-gonic/gin""jwt/middleware""jwt/route" )func main() {r := gin.Default() r.Use(middleware.ValidataToken())route.AddUserInfoRoute(r)r.Run(":8080") }