优化结构

This commit is contained in:
Yvan
2026-08-20 21:46:52 +08:00
parent 23bc29ce0f
commit 63dbb4cfbc
78 changed files with 767 additions and 1082 deletions
+6
View File
@@ -0,0 +1,6 @@
# Security
Security mechanisms used by the application live here. `adminauth` contains
the admin JWT claims, signing, parsing, and normalized token errors. It has no
HTTP or persistence dependency, but it is still application security code and
therefore does not belong in a generic utility package.
+77
View File
@@ -0,0 +1,77 @@
package adminauth
import (
"errors"
"time"
"github.com/golang-jwt/jwt/v5"
)
var (
ErrTokenExpired = errors.New("token expired")
ErrTokenMalformed = errors.New("token malformed")
ErrTokenSignatureInvalid = errors.New("token signature invalid")
ErrTokenNotValidYet = errors.New("token not valid yet")
ErrTokenInvalid = errors.New("token invalid")
)
type Claims struct {
UUID string
ID uint
Username string
NickName string
AuthorityID uint `json:"AuthorityId"`
BufferTime int64
UserType string
MustChangePwd bool `json:"mustChangePwd"`
PasswordVersion int64 `json:"passwordVersion,omitempty"`
jwt.RegisteredClaims
}
func Generate(secret, issuer string, expires, buffer time.Duration, userID, authorityID uint, uuid, username, nickname string, mustChange bool, passwordVersion int64) (string, *Claims, error) {
if secret == "" {
return "", nil, errors.New("empty JWT signing key")
}
now := time.Now()
claims := &Claims{UUID: uuid, ID: userID, Username: username, NickName: nickname, AuthorityID: authorityID, BufferTime: int64(buffer / time.Second), UserType: "admin", MustChangePwd: mustChange, PasswordVersion: passwordVersion, RegisteredClaims: jwt.RegisteredClaims{Audience: jwt.ClaimStrings{"KRA"}, Issuer: issuer, IssuedAt: jwt.NewNumericDate(now), NotBefore: jwt.NewNumericDate(now.Add(-1000)), ExpiresAt: jwt.NewNumericDate(now.Add(expires))}}
token, err := Sign(secret, claims)
return token, claims, err
}
func Sign(secret string, claims *Claims) (string, error) {
if secret == "" {
return "", errors.New("empty JWT signing key")
}
return jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString([]byte(secret))
}
func Parse(tokenString, secret string) (*Claims, error) {
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (any, error) {
if token.Method != jwt.SigningMethodHS256 {
return nil, errors.New("unexpected signing method")
}
return []byte(secret), nil
})
if err != nil {
switch {
case errors.Is(err, jwt.ErrTokenExpired):
return nil, ErrTokenExpired
case errors.Is(err, jwt.ErrTokenMalformed):
return nil, ErrTokenMalformed
case errors.Is(err, jwt.ErrTokenSignatureInvalid):
return nil, ErrTokenSignatureInvalid
case errors.Is(err, jwt.ErrTokenNotValidYet):
return nil, ErrTokenNotValidYet
default:
return nil, ErrTokenInvalid
}
}
if !token.Valid {
return nil, ErrTokenInvalid
}
claims, ok := token.Claims.(*Claims)
if !ok {
return nil, errors.New("token claims are invalid")
}
return claims, nil
}