// 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()) }