Merge pull request #927 from trheyi/main
feat: Upgrade JWT library and enhance token validation
This commit is contained in:
commit
9182a96bb6
3 changed files with 43 additions and 26 deletions
4
go.mod
4
go.mod
|
|
@ -18,11 +18,12 @@ require (
|
||||||
github.com/fatih/color v1.18.0
|
github.com/fatih/color v1.18.0
|
||||||
github.com/fsnotify/fsnotify v1.8.0
|
github.com/fsnotify/fsnotify v1.8.0
|
||||||
github.com/gin-gonic/gin v1.10.0
|
github.com/gin-gonic/gin v1.10.0
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
github.com/golang-jwt/jwt/v4 v4.5.2
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/hashicorp/go-multierror v1.1.1
|
github.com/hashicorp/go-multierror v1.1.1
|
||||||
github.com/joho/godotenv v1.5.1
|
github.com/joho/godotenv v1.5.1
|
||||||
github.com/json-iterator/go v1.1.12
|
github.com/json-iterator/go v1.1.12
|
||||||
|
github.com/mozillazg/go-pinyin v0.20.0
|
||||||
github.com/pkoukk/tiktoken-go v0.1.7
|
github.com/pkoukk/tiktoken-go v0.1.7
|
||||||
github.com/rhysd/go-github-selfupdate v1.2.3
|
github.com/rhysd/go-github-selfupdate v1.2.3
|
||||||
github.com/spf13/cast v1.7.1
|
github.com/spf13/cast v1.7.1
|
||||||
|
|
@ -98,7 +99,6 @@ require (
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||||
github.com/montanaflynn/stats v0.7.1 // indirect
|
github.com/montanaflynn/stats v0.7.1 // indirect
|
||||||
github.com/mozillazg/go-pinyin v0.20.0 // indirect
|
|
||||||
github.com/oklog/run v1.1.0 // indirect
|
github.com/oklog/run v1.1.0 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
|
|
||||||
4
go.sum
4
go.sum
|
|
@ -101,8 +101,8 @@ github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpv
|
||||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||||
github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM=
|
github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM=
|
||||||
github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,10 @@ package helper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
"github.com/yaoapp/gou/process"
|
"github.com/yaoapp/gou/process"
|
||||||
"github.com/yaoapp/gou/session"
|
"github.com/yaoapp/gou/session"
|
||||||
"github.com/yaoapp/kun/any"
|
"github.com/yaoapp/kun/any"
|
||||||
|
|
@ -13,12 +14,19 @@ import (
|
||||||
"github.com/yaoapp/yao/config"
|
"github.com/yaoapp/yao/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// MaxTokenLength is the maximum allowed length for a JWT token
|
||||||
|
MaxTokenLength = 4096
|
||||||
|
// MaxTokenParts is the maximum allowed number of parts in a JWT token (header.payload.signature)
|
||||||
|
MaxTokenParts = 3
|
||||||
|
)
|
||||||
|
|
||||||
// JwtClaims 用户Token
|
// JwtClaims 用户Token
|
||||||
type JwtClaims struct {
|
type JwtClaims struct {
|
||||||
ID int `json:"id"`
|
ID int `json:"id"`
|
||||||
SID string `json:"sid"`
|
SID string `json:"sid"`
|
||||||
Data map[string]interface{} `json:"data"`
|
Data map[string]interface{} `json:"data"`
|
||||||
jwt.StandardClaims
|
jwt.RegisteredClaims
|
||||||
}
|
}
|
||||||
|
|
||||||
// JwtToken JWT令牌
|
// JwtToken JWT令牌
|
||||||
|
|
@ -29,6 +37,18 @@ type JwtToken struct {
|
||||||
|
|
||||||
// JwtValidate JWT 校验
|
// JwtValidate JWT 校验
|
||||||
func JwtValidate(tokenString string, secret ...[]byte) *JwtClaims {
|
func JwtValidate(tokenString string, secret ...[]byte) *JwtClaims {
|
||||||
|
// Check token length
|
||||||
|
if len(tokenString) > MaxTokenLength {
|
||||||
|
exception.New("Token too long", 401).Throw()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check number of parts
|
||||||
|
parts := strings.Split(tokenString, ".")
|
||||||
|
if len(parts) > MaxTokenParts {
|
||||||
|
exception.New("Invalid token format", 401).Throw()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
jwtSecret := []byte(config.Conf.JWTSecret)
|
jwtSecret := []byte(config.Conf.JWTSecret)
|
||||||
if len(secret) > 0 {
|
if len(secret) > 0 {
|
||||||
|
|
@ -62,12 +82,12 @@ func JwtMake(id int, data map[string]interface{}, option map[string]interface{},
|
||||||
jwtSecret = secret[0]
|
jwtSecret = secret[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now().Unix()
|
now := time.Now()
|
||||||
sid := ""
|
sid := ""
|
||||||
timeout := int64(3600)
|
timeout := time.Hour
|
||||||
uid := fmt.Sprintf("%d", id)
|
uid := fmt.Sprintf("%d", id)
|
||||||
subject := "User Token"
|
subject := "User Token"
|
||||||
audience := "Yao Process utils.jwt.Make"
|
audience := []string{"Yao Process utils.jwt.Make"}
|
||||||
issuer := fmt.Sprintf("xiang:%d", id)
|
issuer := fmt.Sprintf("xiang:%d", id)
|
||||||
|
|
||||||
if v, has := option["subject"]; has {
|
if v, has := option["subject"]; has {
|
||||||
|
|
@ -75,7 +95,7 @@ func JwtMake(id int, data map[string]interface{}, option map[string]interface{},
|
||||||
}
|
}
|
||||||
|
|
||||||
if v, has := option["audience"]; has {
|
if v, has := option["audience"]; has {
|
||||||
audience = fmt.Sprintf("%v", v)
|
audience = []string{fmt.Sprintf("%v", v)}
|
||||||
}
|
}
|
||||||
|
|
||||||
if v, has := option["issuer"]; has {
|
if v, has := option["issuer"]; has {
|
||||||
|
|
@ -87,45 +107,42 @@ func JwtMake(id int, data map[string]interface{}, option map[string]interface{},
|
||||||
}
|
}
|
||||||
|
|
||||||
if v, has := option["timeout"]; has {
|
if v, has := option["timeout"]; has {
|
||||||
timeout = int64(any.Of(v).CInt())
|
timeout = time.Duration(any.Of(v).CInt()) * time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
expiresAt := now + timeout
|
expiresAt := now.Add(timeout)
|
||||||
if v, has := option["expires_at"]; has {
|
if v, has := option["expires_at"]; has {
|
||||||
expiresAt = int64(any.Of(v).CInt())
|
expiresAt = time.Unix(int64(any.Of(v).CInt()), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if sid == "" {
|
if sid == "" {
|
||||||
sid = session.ID()
|
sid = session.ID()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设定会话过期时间 (并写需要加锁,这个逻辑需要优化)
|
|
||||||
// session.Global().Expire(time.Duration(timeout) * time.Second)
|
|
||||||
|
|
||||||
claims := &JwtClaims{
|
claims := &JwtClaims{
|
||||||
ID: id,
|
ID: id,
|
||||||
SID: sid, // 会话ID
|
SID: sid, // 会话ID
|
||||||
Data: data,
|
Data: data,
|
||||||
StandardClaims: jwt.StandardClaims{
|
RegisteredClaims: jwt.RegisteredClaims{
|
||||||
Id: uid, // 唯一ID
|
ID: uid, // 唯一ID
|
||||||
Subject: subject, // 主题
|
Subject: subject, // 主题
|
||||||
Audience: audience, // 接收人
|
Audience: audience, // 接收人
|
||||||
ExpiresAt: expiresAt, // 过期时间
|
ExpiresAt: jwt.NewNumericDate(expiresAt), // 过期时间
|
||||||
NotBefore: now, // 生效时间
|
NotBefore: jwt.NewNumericDate(now), // 生效时间
|
||||||
IssuedAt: now, // 签发时间
|
IssuedAt: jwt.NewNumericDate(now), // 签发时间
|
||||||
Issuer: issuer, // 签发人
|
Issuer: issuer, // 签发人
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||||
tokenString, err := token.SignedString([]byte(jwtSecret))
|
tokenString, err := token.SignedString(jwtSecret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exception.New("JWT Make Error: %s", 500, err.Error()).Throw()
|
exception.New("JWT Make Error: %s", 500, err.Error()).Throw()
|
||||||
}
|
}
|
||||||
|
|
||||||
return JwtToken{
|
return JwtToken{
|
||||||
Token: tokenString,
|
Token: tokenString,
|
||||||
ExpiresAt: expiresAt,
|
ExpiresAt: expiresAt.Unix(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue