Files
sc-lktx-mp/sc-lktx-backend/internal/common/utils/jwt.go
huangjin fe3ad20fe2 'init'
2026-06-29 17:34:59 +08:00

102 lines
3.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// JWT Token 生成与解析 + 业务工具函数
package utils
import (
"crypto/rand"
"encoding/hex"
"fmt"
"time"
"github.com/golang-jwt/jwt/v5"
)
// JWTClaims JWT 载荷,包含用户 ID 和角色列表
type JWTClaims struct {
UserID uint `json:"user_id"`
RoleCode string `json:"role_code"` // 角色(visitor/employee/guard)
jwt.RegisteredClaims
}
// AdminJWTClaims 管理员 JWT 载荷
type AdminJWTClaims struct {
AdminID uint `json:"admin_id"`
Account string `json:"account"`
jwt.RegisteredClaims
}
// GenerateAdminToken 生成管理员 JWT
func GenerateAdminToken(adminID uint, account string, secret string, expireHours int) (string, error) {
claims := AdminJWTClaims{
AdminID: adminID,
Account: account,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(expireHours) * time.Hour)),
IssuedAt: jwt.NewNumericDate(time.Now()),
Issuer: "lktx-admin",
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString([]byte(secret))
}
// ParseAdminToken 解析管理员 JWT
func ParseAdminToken(tokenString string, secret string) (*AdminJWTClaims, error) {
token, err := jwt.ParseWithClaims(tokenString, &AdminJWTClaims{}, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return []byte(secret), nil
})
if err != nil {
return nil, err
}
if claims, ok := token.Claims.(*AdminJWTClaims); ok && token.Valid {
return claims, nil
}
return nil, fmt.Errorf("invalid token")
}
// GenerateToken 生成 JWT单角色兼容旧版
func GenerateToken(userID uint, roleCode string, secret string, expireHours int) (string, error) {
claims := JWTClaims{
UserID: userID,
RoleCode: roleCode,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(expireHours) * time.Hour)),
IssuedAt: jwt.NewNumericDate(time.Now()),
Issuer: "lktx-mp",
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString([]byte(secret))
}
// ParseToken 解析并验证 JWT
func ParseToken(tokenString string, secret string) (*JWTClaims, error) {
token, err := jwt.ParseWithClaims(tokenString, &JWTClaims{}, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return []byte(secret), nil
})
if err != nil {
return nil, err
}
if claims, ok := token.Claims.(*JWTClaims); ok && token.Valid {
return claims, nil
}
return nil, fmt.Errorf("invalid token")
}
// GenerateInviteCode 生成 16 位随机邀请码
func GenerateInviteCode() string {
b := make([]byte, 8)
rand.Read(b)
return hex.EncodeToString(b)
}
// GenerateQRCodeContent 生成二维码内容
func GenerateQRCodeContent(appointmentID uint) string {
return fmt.Sprintf("LKTX:APPT:%d:%d", appointmentID, time.Now().Unix())
}