113 lines
3.0 KiB
Go
113 lines
3.0 KiB
Go
|
|
package service
|
||
|
|
|
||
|
|
import (
|
||
|
|
apperrors "carrotskin/internal/errors"
|
||
|
|
"carrotskin/internal/repository"
|
||
|
|
"context"
|
||
|
|
"fmt"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"go.uber.org/zap"
|
||
|
|
)
|
||
|
|
|
||
|
|
// CertificateService 证书服务接口
|
||
|
|
type CertificateService interface {
|
||
|
|
// GeneratePlayerCertificate 生成玩家证书
|
||
|
|
GeneratePlayerCertificate(ctx context.Context, uuid string) (map[string]interface{}, error)
|
||
|
|
// GetPublicKey 获取公钥
|
||
|
|
GetPublicKey(ctx context.Context) (string, error)
|
||
|
|
}
|
||
|
|
|
||
|
|
// yggdrasilCertificateService 证书服务实现
|
||
|
|
type yggdrasilCertificateService struct {
|
||
|
|
profileRepo repository.ProfileRepository
|
||
|
|
signatureService *signatureService
|
||
|
|
logger *zap.Logger
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewCertificateService 创建证书服务实例
|
||
|
|
func NewCertificateService(
|
||
|
|
profileRepo repository.ProfileRepository,
|
||
|
|
signatureService *signatureService,
|
||
|
|
logger *zap.Logger,
|
||
|
|
) CertificateService {
|
||
|
|
return &yggdrasilCertificateService{
|
||
|
|
profileRepo: profileRepo,
|
||
|
|
signatureService: signatureService,
|
||
|
|
logger: logger,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// GeneratePlayerCertificate 生成玩家证书
|
||
|
|
func (s *yggdrasilCertificateService) GeneratePlayerCertificate(ctx context.Context, uuid string) (map[string]interface{}, error) {
|
||
|
|
if uuid == "" {
|
||
|
|
return nil, apperrors.ErrUUIDRequired
|
||
|
|
}
|
||
|
|
|
||
|
|
s.logger.Info("开始生成玩家证书",
|
||
|
|
zap.String("uuid", uuid),
|
||
|
|
)
|
||
|
|
|
||
|
|
// 获取密钥对
|
||
|
|
keyPair, err := s.profileRepo.GetKeyPair(uuid)
|
||
|
|
if err != nil {
|
||
|
|
s.logger.Info("获取用户密钥对失败,将创建新密钥对",
|
||
|
|
zap.Error(err),
|
||
|
|
zap.String("uuid", uuid),
|
||
|
|
)
|
||
|
|
keyPair = nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// 如果没有找到密钥对或密钥对已过期,创建一个新的
|
||
|
|
now := time.Now().UTC()
|
||
|
|
if keyPair == nil || keyPair.Refresh.Before(now) || keyPair.PrivateKey == "" || keyPair.PublicKey == "" {
|
||
|
|
s.logger.Info("为用户创建新的密钥对",
|
||
|
|
zap.String("uuid", uuid),
|
||
|
|
)
|
||
|
|
keyPair, err = s.signatureService.NewKeyPair()
|
||
|
|
if err != nil {
|
||
|
|
s.logger.Error("生成玩家证书密钥对失败",
|
||
|
|
zap.Error(err),
|
||
|
|
zap.String("uuid", uuid),
|
||
|
|
)
|
||
|
|
return nil, fmt.Errorf("生成玩家证书密钥对失败: %w", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
// 保存密钥对到数据库
|
||
|
|
err = s.profileRepo.UpdateKeyPair(uuid, keyPair)
|
||
|
|
if err != nil {
|
||
|
|
s.logger.Warn("更新用户密钥对失败",
|
||
|
|
zap.Error(err),
|
||
|
|
zap.String("uuid", uuid),
|
||
|
|
)
|
||
|
|
// 继续执行,即使保存失败
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 计算expiresAt的毫秒时间戳
|
||
|
|
expiresAtMillis := keyPair.Expiration.UnixMilli()
|
||
|
|
|
||
|
|
// 返回玩家证书
|
||
|
|
certificate := map[string]interface{}{
|
||
|
|
"keyPair": map[string]interface{}{
|
||
|
|
"privateKey": keyPair.PrivateKey,
|
||
|
|
"publicKey": keyPair.PublicKey,
|
||
|
|
},
|
||
|
|
"publicKeySignature": keyPair.PublicKeySignature,
|
||
|
|
"publicKeySignatureV2": keyPair.PublicKeySignatureV2,
|
||
|
|
"expiresAt": expiresAtMillis,
|
||
|
|
"refreshedAfter": keyPair.Refresh.UnixMilli(),
|
||
|
|
}
|
||
|
|
|
||
|
|
s.logger.Info("成功生成玩家证书",
|
||
|
|
zap.String("uuid", uuid),
|
||
|
|
)
|
||
|
|
return certificate, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetPublicKey 获取公钥
|
||
|
|
func (s *yggdrasilCertificateService) GetPublicKey(ctx context.Context) (string, error) {
|
||
|
|
return s.signatureService.GetPublicKeyFromRedis()
|
||
|
|
}
|
||
|
|
|