package utils import ( "errors" "strings" "time" "github.com/dgrijalva/jwt-go" ) const ( userIDKey = "userId" ipKey = "ip" uaKey = "ua" ) type IPClaims struct { Ip string Expire time.Duration UA string } func GenerateIpToken(claims IPClaims, secret string) (string, error) { return generateToken(jwt.MapClaims{ ipKey: claims.Ip, uaKey: claims.UA, "exp": Now().Add(claims.Expire).Unix(), "issuer": "com.butterfly", "sub": "asign", "aud": "public", }, []byte(secret)) } func ParseIpToken(tokenString string, secret string) (pass bool, ip, ua string, err error) { t, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { return []byte(secret), nil }) var isExpire *bool if vErr, ok := err.(*jwt.ValidationError); ok { e := vErr.Errors&jwt.ValidationErrorExpired > 0 isExpire = &e } if err != nil || isExpire == nil { return } var ok bool var jc jwt.MapClaims jc, ok = t.Claims.(jwt.MapClaims) if !ok { err = errors.New("parse token fail") return } ip, ok = jc[ipKey].(string) if !ok { err = errors.New("parse token fail") return } ua, ok = jc[uaKey].(string) if !ok { err = errors.New("parse token fail") return } pass = true return } type UserClaims struct { UserID int64 Expire time.Duration } func generateToken(claims jwt.MapClaims, secret []byte) (string, error) { return jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString(secret) } func GenerateUserToken(claims UserClaims, secret string) (string, error) { return generateToken(jwt.MapClaims{ userIDKey: claims.UserID, "exp": Now().Add(claims.Expire).Unix(), "issuer": "com.butterfly", "sub": "asign", "aud": "public", }, []byte(secret)) } // ParseToken 解析Token func ParseUserToken(token string, secret string) (userId int64, newToken string, err error) { t, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) { return []byte(secret), nil }) var isExpire *bool if vErr, ok := err.(jwt.ValidationError); ok { e := vErr.Errors&jwt.ValidationErrorExpired > 0 isExpire = &e } if err != nil && isExpire == nil { return } jc, ok := t.Claims.(jwt.MapClaims) if !ok { err = errors.New("unknown token error1") return } id, ok := jc[userIDKey].(float64) if !ok { err = errors.New("unknown token error1") return } userId = int64(id) if isExpire != nil && *isExpire { newToken, err = GenerateUserToken(UserClaims{UserID: userId, Expire: 30 * 24 * time.Hour}, secret) return } err = nil return } // Strips 'Bearer ' prefix from bearer token string func StripBearerPrefixFromTokenString(tok string) string { if len(tok) > 6 && strings.ToUpper(tok[0:7]) == "BEARER " { return tok[7:] } else { return tok } }