4.1.2 生成JWT-string(核心代码)
1.自定义payload结构体,不建议直接使用 dgrijalva/jwt-go jwt.StandardClaims结构体.因为他的payload包含的用户信息太少.
2.实现 type Claims interface 的 Valid() error 方法,自定义校验内容
3.生成JWT-string jwtGenerateToken(m *User,d time.Duration) (string, error)
https://github.com/libragen/felix/blob/master/model/m_jwt.go
package model
import (
"errors"
"fmt"
"time"
"github.com/dgrijalva/jwt-go"
"github.com/sirupsen/logrus"
)
var AppSecret = ""//viper.GetString会设置这个值(32byte长度)
var AppIss = "github.com/libragen/felix"//这个值会被viper.GetString重写
//自定义payload结构体,不建议直接使用 dgrijalva/jwt-go `jwt.StandardClaims`结构体.因为他的payload包含的用户信息太少.
type userStdClaims struct {
jwt.StandardClaims
*User
}
//实现 `type Claims interface` 的 `Valid() error` 方法,自定义校验内容
func (c userStdClaims) Valid() (err error) {
if c.VerifyExpiresAt(time.Now().Unix(), true) == false {
return errors.New("token is expired")
}
if !c.VerifyIssuer(AppIss, true) {
return errors.New("token's issuer is wrong")
}
if c.User.Id < 1 {
return errors.New("invalid user in jwt")
}
return
}
func jwtGenerateToken(m *User,d time.Duration) (string, error) {
m.Password = ""
expireTime := time.Now().Add(d)
stdClaims := jwt.StandardClaims{
ExpiresAt: expireTime.Unix(),
IssuedAt: time.Now().Unix(),
Id: fmt.Sprintf("%d", m.Id),
Issuer: AppIss,
}
uClaims := userStdClaims{
StandardClaims: stdClaims,
User: m,
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, uClaims)
// Sign and get the complete encoded token as a string using the secret
tokenString, err := token.SignedString([]byte(AppSecret))
if err != nil {
logrus.WithError(err).Fatal("config is wrong, can not generate jwt")
}
return tokenString, err
}
//JwtParseUser 解析payload的内容,得到用户信息
//gin-middleware 会使用这个方法
func JwtParseUser(tokenString string) (*User, error) {
if tokenString == "" {
return nil, errors.New("no token is found in Authorization Bearer")
}
claims := userStdClaims{}
_, err := jwt.ParseWithClaims(tokenString, &claims, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return []byte(AppSecret), nil
})
if err != nil {
return nil, err
}
return claims.User, err
}
4.2 JWT中间件(middleware)
1.从url-query的_t获取JWT-string或者从请求头 Authorization中获取JWT-string
2.model.JwtParseUser(token)解析JWT-string获取User结构体(减少中间件查询数据库的操作和时间)
3.设置用户信息到gin.Context 其他的handler通过gin.Context.Get(contextKeyUserObj),在进行用户Type Assert得到model.User 结构体.









