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))
}

你可能感兴趣的:(go)