因为青训营的token没有放在请求头中,所以需要分别读取token,然后再做判断, 下面是jwt设置:
var jwtKey = []byte("a_secret_key")
type Claims struct {
UserId uint
jwt.StandardClaims
}
// 发放jwt
func ReleaseToken(user model.User) (string, error) {
// token的有效期
expirationTime := time.Now().Add(7 * 24 * time.Hour)
claims := &Claims{
// 自定义字段
UserId: user.ID,
// 标准字段
StandardClaims: jwt.StandardClaims{
// 过期时间
ExpiresAt: expirationTime.Unix(),
// 发放时间
IssuedAt: time.Now().Unix(),
},
}
// 使用jwt密钥生成token
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString(jwtKey)
if err != nil {
return "", err
}
// 返回token
return tokenString, nil
}
// 验证jwt
func ParseToken(tokenString string) (*jwt.Token, *Claims, error) {
claims := &Claims{}
token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (i interface{}, err error) {
return jwtKey, nil
})
return token, claims, err
}
下面是token验证的中间件
// 读取body中的token
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 读取请求token
var requestToken string
if c.Request.Method == "GET" {
requestToken = c.Query("token")
} else if c.Request.Method == "POST" {
requestToken = c.PostForm("token")
}
// token为空
if requestToken == "" {
c.JSON(http.StatusUnauthorized, gin.H{
"status_code": 401,
"status_msg": "缺少token",
})
c.Abort()
return
}
// 解析token
token, claims, err := common.ParseToken(requestToken)
// token非法
if err != nil || !token.Valid {
c.JSON(http.StatusUnauthorized, gin.H{
"status_code": 401,
"status_msg": "token非法",
})
c.Abort()
return
}
// 获取claims中的userId
userId := claims.UserId
DB := common.GetDB()
var user model.User
DB.Where("id =?", userId).First(&user)
if user.ID == 0 {
c.JSON(http.StatusBadRequest, gin.H{
"status_code": 401,
"status_msg": "token无效",
})
c.Abort()
return
}
// 将用户信息写入上下文便于读取
c.Set("user", user)
c.Next()
}
}