feat: 客户端授权防护——响应签名/激活令牌/宽限期/换座限制/在线清扫/疑似共享标记

This commit is contained in:
Logan.Li committed 2026-09-14 21:08:39 +08:00
1 parent 37d9e8ca56
commit b76111dfc3
11 files changed
+437 -54

No files matched your search

@@ -1,12 +1,14 @@
package license
import (
"backend/config"
"backend/internal/dto"
"backend/internal/model"
customersvc "backend/internal/service/customer"
"backend/utils"
"encoding/json"
"errors"
"log"
"strconv"
"strings"
"time"
@@ -16,12 +18,32 @@ import (
// LicenseService License 业务逻辑层 // Logan.Li
type LicenseService struct {
db *gorm.DB
db *gorm.DB
cfg *config.Config
guard *clientGuard
}
// NewLicenseService 创建 service 实例 // Logan.Li
func NewLicenseService(db *gorm.DB) *LicenseService {
return &LicenseService{db: db}
// NewLicenseService 创建 service 实例(cfg 提供防护配置与响应签名密钥) // Logan.Li
func NewLicenseService(db *gorm.DB, cfg *config.Config) *LicenseService {
svc := &LicenseService{db: db, cfg: cfg}
if cfg != nil {
g := &clientGuard{
gracePeriodDays: cfg.GracePeriodDays,
activateDailyLimit: cfg.ActivateDailyLimit,
onlineTTLMinutes: cfg.OnlineTTLMinutes,
deactivateRequireToken: cfg.DeactivateRequireToken,
}
if seed := strings.TrimSpace(cfg.OfflineLicenseSeed); seed != "" {
if kp, err := utils.DeriveOfflineKeyPair(seed); err == nil {
g.kp = kp
} else {
// seed 非法只降级签名能力,不阻断启动(离线签发侧会再次报错) // Logan.Li
log.Printf("[安全] 离线 seed 派生失败,响应签名将不可用: %v", err)
}
}
svc.guard = g
}
return svc
}
// ListQuery 列表查询参数 // Logan.Li
@@ -67,7 +89,9 @@ func (s *LicenseService) List(page, pageSize int, q ListQuery) ([]dto.LicenseRes
results := make([]dto.LicenseResponse, 0, len(licenses))
for _, l := range licenses {
results = append(results, toLicenseResponse(l))
resp := toLicenseResponse(l)
attachAbuseStats(&resp, l)
results = append(results, resp)
}
return results, total, nil
}
@@ -81,6 +105,7 @@ func (s *LicenseService) GetByID(id uint) (*dto.LicenseResponse, []dto.Activatio
}
resp := toLicenseResponse(lic)
attachAbuseStats(&resp, lic)
activations := make([]dto.ActivationResponse, 0, len(lic.Activations))
for _, a := range lic.Activations {
activations = append(activations, toActivationResponse(a))
@@ -180,9 +205,9 @@ func (s *LicenseService) Delete(id uint) (*model.License, error) {
// BatchDeleteResult 批量删除结果 // Logan.Li
type BatchDeleteResult struct {
Deleted int `json:"deleted"`
Skipped int `json:"skipped"`
Failed int `json:"failed"`
Deleted int `json:"deleted"`
Skipped int `json:"skipped"`
Failed int `json:"failed"`
SkippedIDs []uint `json:"skipped_ids,omitempty"`
}