Jwt的使用
Jwt的使用
准备自定义结构体
// 存储的数据
type JwtPayLoad struct {
UserName string `json:"username"`
NickName string `json:"nick_name"`
Role int `json:"role"`
UserId uint `json:"user_id"`
Avatar string `json:"avatar"`
}
// 将jwt.RegisteredClaims嵌套到CustomClaims中,用来扩展自定义内容和继承Claims
type CustomClaims struct {
JwtPayLoad
jwt.RegisteredClaims
}
使用 NewWithClaims 函数生成 token
func NewWithClaims(method SigningMethod, claims Claims) *Token {
return &Token{
Header: map[string]interface{}{
"typ": "JWT",
"alg": method.Alg(),
},
Claims: claims,
Method: method,
}
}
// jwt.RegisteredClaims实现了Valid接口,继承了Claims
type Claims interface {
Valid() error
}
生成 token
func GenToken(payLoad JwtPayLoad, secret string, expires int64) (string, error) {
claim := CustomClaims{
JwtPayLoad: payLoad,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * time.Duration(expires))),
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claim)
return token.SignedString([]byte(secret))
}
解析 token,需要密钥鉴权
func ParseToken(secret, tokenStr string) (*CustomClaims, error) {
token, err := jwt.ParseWithClaims(tokenStr, &CustomClaims{}, func(t *jwt.Token) (interface{}, error) {
return []byte(secret), nil
})
if err != nil {
log.Println(fmt.Sprintf("token解析错误: %s", err.Error()))
return nil, err
}
if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
return claims, nil
}
return nil, errors.New("token非法")
}
注意:不要在 jwt 中存储敏感信息,jwt 中的 payload 部分只是使用了 base64 对内容进行了编码,并没有加密,主要是通过 jwt 的 signature 部分对整个 jwt 进行验证
验证方式:服务器会使用与生成 jwt 时相同的密钥和签名算法,对头部和载荷重新进行签名,并将新生成的签名与 jwt 中的签名进行比较,同时检查过期时间

浙公网安备 33010602011771号