依赖安装
go get -u github.com/golang-jwt/jwt/v5
文档地址
文档
创建对象
jwt的相关配置
# jwt configuration
jwt:signing-key: xxxexpires-time: 7dbuffer-time: 1dissuer: fancy_fishclaim-strings: fancy_fish_to_do_list
claims类型配置
package requestimport ("github.com/golang-jwt/jwt/v5""github.com/google/uuid"
)type BaseClaims struct {UUID uuid.UUIDUsername stringjwt.RegisteredClaims
}type CustomClaims struct {BaseClaimsBufferTime int64jwt.RegisteredClaims
}
代码示例
package utilimport ("ToDoList/enum""ToDoList/global""ToDoList/model/request""fmt""github.com/gin-gonic/gin"jwt "github.com/golang-jwt/jwt/v5""net""time"
)type _jwt struct {SigningKey []byteClaims jwt.Claims
}
// 解析token 验证是否有效
func (receiver *_jwt) ValidateToken(tokenString string) (*request.CustomClaims, error) {token, err := jwt.ParseWithClaims(tokenString, &request.CustomClaims{}, func(token *jwt.Token) (i interface{}, e error) {return receiver.SigningKey, nil})if err != nil {fmt.Println(err, "token验证错误")return nil, err}if token != nil {if claims, ok := token.Claims.(*request.CustomClaims); ok && token.Valid {return claims, nil}return nil, enum.TokenInvalid} else {return nil, enum.TokenInvalid}
}func (receiver *_jwt) CreateToken(claims request.CustomClaims) (string, error) {t := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)token, err := t.SignedString(receiver.SigningKey)if err != nil {fmt.Println("toen生成失败")return token, err}return token, nil
}// 创建生成token必须的clasims
func (receiver *_jwt) CreateClaims(baseClaims request.BaseClaims) request.CustomClaims {// 按天解析,time.ParseDuration()不支持按天。bft, _ := BasicUtils.ParseDuration(global.GVA_CONFIG.JWT.BufferTime)ept, _ := BasicUtils.ParseDuration(global.GVA_CONFIG.JWT.ExpiresTime)claims := request.CustomClaims{BaseClaims: baseClaims,BufferTime: int64(bft / time.Second), // 缓冲时间1天 缓冲时间内会获得新的token刷新令牌 此时一个用户会存在两个有效令牌 但是前端只留一个 另一个会丢失RegisteredClaims: jwt.RegisteredClaims{Audience: jwt.ClaimStrings{global.GVA_CONFIG.JWT.ClaimStrings}, // 受众NotBefore: jwt.NewNumericDate(time.Now().Add(-1000)), // 签名生效时间ExpiresAt: jwt.NewNumericDate(time.Now().Add(ept)), // 过期时间 7天 配置文件Issuer: global.GVA_CONFIG.JWT.Issuer, // 签名的发行者},}return claims
}func JWTNew() *_jwt {return &_jwt{SigningKey: []byte(global.GVA_CONFIG.JWT.SigningKey),}
}var JWTToken = JWTNew()func SetToken(c *gin.Context, token string, maxAge int) {// 增加cookie x-token 向来源的web添加host, _, err := net.SplitHostPort(c.Request.Host)if err != nil {host = c.Request.Host}if net.ParseIP(host) != nil {c.SetCookie("x-token", token, maxAge, "/", "", false, false)} else {c.SetCookie("x-token", token, maxAge, "/", host, false, false)}
}func GetToken(c *gin.Context) string {token, _ := c.Cookie("x-token")if token == "" {token = c.Request.Header.Get("x-token")}return token
}
按天解析时间
func (receiver basicUtils) ParseDuration(d string) (time.Duration, error) {d = strings.TrimSpace(d)dr, err := time.ParseDuration(d)if err == nil {return dr, nil}if strings.Contains(d, "d") {index := strings.Index(d, "d")hour, _ := strconv.Atoi(d[:index])dr = time.Hour * 24 * time.Duration(hour)ndr, err := time.ParseDuration(d[index+1:])if err != nil {return dr, nil}return dr + ndr, nil}dv, err := strconv.ParseInt(d, 10, 64)return time.Duration(dv), err
}
生成token
j := util.JWTNew()claims := j.CreateClaims(request.BaseClaims{UUID: u.UUID,Username: u.Username,})token, err := j.CreateToken(claims)
总结
Token的组成成分
- 秘钥这个自定义一个字符串即可
- 声明名称的列表可以将用户名或 ID 或角色编码到令牌中,也可以称为载荷
- 签名算法
关键函数的签名
func NewWithClaims(method SigningMethod, claims Claims, opts ...TokenOption) *Token
JWT-GO使用主要有以下步骤
- 配置私钥
NewWithClaims
传入方法和声明- 通过
SignedString
创建token ParseWithClaims
传入token解析token