68 lines
1.8 KiB
Go
68 lines
1.8 KiB
Go
package commonservice
|
||
|
||
import (
|
||
"time"
|
||
|
||
"github.com/golang-jwt/jwt/v5"
|
||
)
|
||
|
||
// Claims 是 access / refresh token 的载荷。
|
||
type Claims struct {
|
||
UserID int64 `json:"userId"`
|
||
Username string `json:"username"`
|
||
Type string `json:"type"` // access | refresh
|
||
jwt.RegisteredClaims
|
||
}
|
||
|
||
// IssueAccess 签发 access token。
|
||
func IssueAccess(secret string, userID int64, username string, ttlHours int) (string, error) {
|
||
if ttlHours <= 0 {
|
||
ttlHours = 2
|
||
}
|
||
return issue(secret, userID, username, "access", time.Duration(ttlHours)*time.Hour)
|
||
}
|
||
|
||
// IssueRefresh 签发 refresh token。
|
||
func IssueRefresh(secret string, userID int64, username string, ttlDays int) (string, error) {
|
||
if ttlDays <= 0 {
|
||
ttlDays = 30
|
||
}
|
||
return issue(secret, userID, username, "refresh", time.Duration(ttlDays)*24*time.Hour)
|
||
}
|
||
|
||
func issue(secret string, userID int64, username, typ string, ttl time.Duration) (string, error) {
|
||
now := time.Now()
|
||
claims := Claims{
|
||
UserID: userID,
|
||
Username: username,
|
||
Type: typ,
|
||
RegisteredClaims: jwt.RegisteredClaims{
|
||
IssuedAt: jwt.NewNumericDate(now),
|
||
ExpiresAt: jwt.NewNumericDate(now.Add(ttl)),
|
||
},
|
||
}
|
||
t := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||
return t.SignedString([]byte(secret))
|
||
}
|
||
|
||
// Parse 校验并解析 JWT;typ 非空时要求 claims.Type 匹配。
|
||
func Parse(secret, token, typ string) (*Claims, error) {
|
||
parsed, err := jwt.ParseWithClaims(token, &Claims{}, func(t *jwt.Token) (any, error) {
|
||
if t.Method != jwt.SigningMethodHS256 {
|
||
return nil, Unauthorized("UNAUTHORIZED")
|
||
}
|
||
return []byte(secret), nil
|
||
})
|
||
if err != nil || !parsed.Valid {
|
||
return nil, Unauthorized("UNAUTHORIZED")
|
||
}
|
||
claims, ok := parsed.Claims.(*Claims)
|
||
if !ok || claims.UserID <= 0 {
|
||
return nil, Unauthorized("UNAUTHORIZED")
|
||
}
|
||
if typ != "" && claims.Type != typ {
|
||
return nil, Unauthorized("UNAUTHORIZED")
|
||
}
|
||
return claims, nil
|
||
}
|