golang(gin) 接入jwt,使用token驗證身份

1)這裏使用開源的 jwt-go

1.token 工具類

package handler

import (
	"awesomeProject/utils"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"time"
)
//用戶信息類,作爲生成token的參數
type UserClaims struct {
	ID    string `json:"userId"`
	Name  string `json:"name"`
	Phone string `json:"phone"`
	//jwt-go提供的標準claim
	jwt.StandardClaims
}

var (
	//自定義的token祕鑰
	secret = []byte("16849841325189456f487")
	//該路由下不校驗token
	noVerify = []interface{}{"/login", "/ping"}
	//token有效時間(納秒)
	effectTime = 2 * time.Hour
)

// 生成token
func GenerateToken(claims *UserClaims) string {
	//設置token有效期,也可不設置有效期,採用redis的方式
	//   1)將token存儲在redis中,設置過期時間,token如沒過期,則自動刷新redis過期時間,
	//   2)通過這種方式,可以很方便的爲token續期,而且也可以實現長時間不登錄的話,強制登錄
	//本例只是簡單採用 設置token有效期的方式,只是提供了刷新token的方法,並沒有做續期處理的邏輯
	claims.ExpiresAt = time.Now().Add(effectTime).Unix()
	//生成token
	sign, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString(secret)
	if err != nil {
		//這裏因爲項目接入了統一異常處理,所以使用panic並不會使程序終止,如不接入,可使用原始方式處理錯誤
		//接入統一異常可參考 https://blog.csdn.net/u014155085/article/details/106733391
		panic(err)
	}
	return sign
}

//驗證token
func JwtVerify(c *gin.Context) {
	//過濾是否驗證token
	if utils.IsContainArr(noVerify, c.Request.RequestURI) {
		return
	}
	token := c.GetHeader("token")
	if token == "" {
		panic("token not exist !")
	}
	//驗證token,並存儲在請求中
	c.Set("user", parseToken(token))
}

// 解析Token
func parseToken(tokenString string) *UserClaims {
	//解析token
	token, err := jwt.ParseWithClaims(tokenString, &UserClaims{}, func(token *jwt.Token) (interface{}, error) {
		return secret, nil
	})
	if err != nil {
		panic(err)
	}
	claims, ok := token.Claims.(*UserClaims)
	if !ok {
		panic("token is valid")
	}
	return claims
}

// 更新token
func Refresh(tokenString string) string {
	jwt.TimeFunc = func() time.Time {
		return time.Unix(0, 0)
	}
	token, err := jwt.ParseWithClaims(tokenString, &UserClaims{}, func(token *jwt.Token) (interface{}, error) {
		return secret, nil
	})
	if err != nil {
		panic(err)
	}
	claims, ok := token.Claims.(*UserClaims)
	if !ok {
		panic("token is valid")
	}
	jwt.TimeFunc = time.Now
	claims.StandardClaims.ExpiresAt = time.Now().Add(2 * time.Hour).Unix()
	return GenerateToken(claims)
}

2. 使用該中間件

func main() {
	router := gin.Default()
	router.Use(handler.JwtVerify)

	router.GET("/ping", controller.Ping)
	router.GET("/login", controller.Login)
	router.GET("/userInfo", controller.UserInfo)

	router.Run(":8888") // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")

}

3. controller部分代碼

package controller

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

func Ping(c *gin.Context) {
	c.JSON(http.StatusOK, utils.ResultT("this is ping"))
}

func Login(c *gin.Context) {
	c.JSON(http.StatusOK, utils.ResultT(gin.H{
		"token": handler.GenerateToken(&handler.UserClaims{
			ID:             "001",
			Name:           "張三",
			Phone:          "189***0023",
			StandardClaims: jwt.StandardClaims{},
		}),
	}))

}

func UserInfo(c *gin.Context) {
	user, _ := c.Get("user")
	claims := user.(*handler.UserClaims)
	c.JSON(http.StatusOK, utils.ResultT(claims.Phone))
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章