优化结构
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
module code.yun.ink/pkg/jwtx
|
module code.yun.ink/pkg/jwtx
|
||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
|
require github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||||
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package jwtx
|
package jwtx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -8,80 +9,78 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
TokenExpired error = errors.New("token is expired")
|
ErrTokenExpired error = errors.New("token is expired")
|
||||||
TokenNotValidYet error = errors.New("token not active yet")
|
ErrTokenNotValidYet error = errors.New("token not active yet")
|
||||||
TokenMalformed error = errors.New("that's not even a token")
|
ErrTokenMalformed error = errors.New("that's not even a token")
|
||||||
TokenInvalid error = errors.New("couldn't handle this token")
|
ErrTokenInvalid error = errors.New("couldn't handle this token")
|
||||||
TokenGenerateFailed error = errors.New("generate token failed!")
|
ErrTokenGenerateFailed error = errors.New("generate token failed!")
|
||||||
|
|
||||||
// defaultSignKey string = "hcVI@Nm4cjhjPVvCpL5^1%jY"
|
|
||||||
defaultSignKey = "XiaoXinPlus"
|
|
||||||
|
|
||||||
RedisUserKey string = "user:%d"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type jwtx struct {
|
type jwtx struct {
|
||||||
SigningKey []byte
|
SignKey []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type Claims struct {
|
type Claims struct {
|
||||||
TenantId int64 `json:"tenant_id"`
|
UserData string `json:"user_data"`
|
||||||
ClientId int64 `json:"client_id"`
|
|
||||||
UserId int64 `json:"user_id"`
|
|
||||||
|
|
||||||
Tag string `json:"tag"` // 额外标记
|
|
||||||
|
|
||||||
jwt.StandardClaims
|
jwt.StandardClaims
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewJWT() *jwtx {
|
func NewJWT(signKey string) *jwtx {
|
||||||
return &jwtx{
|
return &jwtx{
|
||||||
[]byte(defaultSignKey),
|
[]byte(signKey),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 仅解析Token
|
// 仅解析Token
|
||||||
func (j *jwtx) Decode(tokenString string) (*Claims, error) {
|
func (j *jwtx) Decode(tokenString string, userData interface{}) error {
|
||||||
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
|
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
|
||||||
return j.SigningKey, nil
|
return j.SignKey, nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if ve, ok := err.(*jwt.ValidationError); ok {
|
if ve, ok := err.(*jwt.ValidationError); ok {
|
||||||
if ve.Errors&jwt.ValidationErrorMalformed == jwt.ValidationErrorMalformed {
|
if ve.Errors&jwt.ValidationErrorMalformed == jwt.ValidationErrorMalformed {
|
||||||
return nil, TokenMalformed
|
return ErrTokenMalformed
|
||||||
} else if ve.Errors&jwt.ValidationErrorExpired == jwt.ValidationErrorExpired {
|
} else if ve.Errors&jwt.ValidationErrorExpired == jwt.ValidationErrorExpired {
|
||||||
// Token is expired
|
// Token is expired
|
||||||
return nil, TokenExpired
|
return ErrTokenExpired
|
||||||
} else if ve.Errors&jwt.ValidationErrorNotValidYet == jwt.ValidationErrorNotValidYet {
|
} else if ve.Errors&jwt.ValidationErrorNotValidYet == jwt.ValidationErrorNotValidYet {
|
||||||
return nil, TokenNotValidYet
|
return ErrTokenNotValidYet
|
||||||
} else {
|
} else {
|
||||||
return nil, TokenInvalid
|
return ErrTokenInvalid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
claims, ok := token.Claims.(*Claims)
|
claims, ok := token.Claims.(*Claims)
|
||||||
if !ok || !token.Valid {
|
if !ok || !token.Valid {
|
||||||
return nil, TokenInvalid
|
return ErrTokenInvalid
|
||||||
}
|
}
|
||||||
return claims, nil
|
|
||||||
|
return json.Unmarshal([]byte(claims.UserData), userData)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据参数生成和设置 token
|
// 根据参数生成和设置 token
|
||||||
func (j *jwtx) Encode(claims *Claims, expiresTime time.Time) (string, error) {
|
func (j *jwtx) Encode(userData interface{}, expiresTime time.Time) (string, error) {
|
||||||
|
|
||||||
expSecond := expiresTime.Unix()
|
if expiresTime.Before(time.Now()) {
|
||||||
nowSecond := time.Now().Unix()
|
|
||||||
|
|
||||||
if expSecond-nowSecond < 0 {
|
|
||||||
return "", errors.New("时间无效")
|
return "", errors.New("时间无效")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db, err := json.Marshal(userData)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.New("json序列化失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
claims := Claims{
|
||||||
|
UserData: string(db),
|
||||||
|
}
|
||||||
|
|
||||||
// 设置有效时间
|
// 设置有效时间
|
||||||
claims.StandardClaims.ExpiresAt = expiresTime.Unix()
|
claims.StandardClaims.ExpiresAt = expiresTime.Unix()
|
||||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||||
tokenString, err := token.SignedString(j.SigningKey)
|
tokenString, err := token.SignedString(j.SignKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", TokenGenerateFailed
|
return "", ErrTokenGenerateFailed
|
||||||
}
|
}
|
||||||
return tokenString, nil
|
return tokenString, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package jwtx_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"code.yun.ink/pkg/jwtx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestJwt(t *testing.T) {
|
||||||
|
u := UserData{
|
||||||
|
UserId: 1,
|
||||||
|
UserName: "test",
|
||||||
|
}
|
||||||
|
j := jwtx.NewJWT("test")
|
||||||
|
s, err := j.Encode(u, time.Now().AddDate(0, 0, 1))
|
||||||
|
fmt.Println(s, err)
|
||||||
|
// var u2 UserData
|
||||||
|
u2 := UserData{}
|
||||||
|
err = j.Decode(s, &u2)
|
||||||
|
fmt.Println(u2, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserData struct {
|
||||||
|
UserId int64 `json:"user_id"`
|
||||||
|
UserName string `json:"user_name"`
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user