| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- package service
- import (
- "context"
- "fmt"
- infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
- "github.com/Wei-Shaw/sub2api/internal/pkg/logger"
- )
- var (
- ErrTurnstileVerificationFailed = infraerrors.BadRequest("TURNSTILE_VERIFICATION_FAILED", "turnstile verification failed")
- ErrTurnstileNotConfigured = infraerrors.ServiceUnavailable("TURNSTILE_NOT_CONFIGURED", "turnstile not configured")
- ErrTurnstileInvalidSecretKey = infraerrors.BadRequest("TURNSTILE_INVALID_SECRET_KEY", "invalid turnstile secret key")
- )
- // TurnstileVerifier 验证 Turnstile token 的接口
- type TurnstileVerifier interface {
- VerifyToken(ctx context.Context, secretKey, token, remoteIP string) (*TurnstileVerifyResponse, error)
- }
- // TurnstileService Turnstile 验证服务
- type TurnstileService struct {
- settingService *SettingService
- verifier TurnstileVerifier
- }
- // TurnstileVerifyResponse Cloudflare Turnstile 验证响应
- type TurnstileVerifyResponse struct {
- Success bool `json:"success"`
- ChallengeTS string `json:"challenge_ts"`
- Hostname string `json:"hostname"`
- ErrorCodes []string `json:"error-codes"`
- Action string `json:"action"`
- CData string `json:"cdata"`
- }
- // NewTurnstileService 创建 Turnstile 服务实例
- func NewTurnstileService(settingService *SettingService, verifier TurnstileVerifier) *TurnstileService {
- return &TurnstileService{
- settingService: settingService,
- verifier: verifier,
- }
- }
- // VerifyToken 验证 Turnstile token
- func (s *TurnstileService) VerifyToken(ctx context.Context, token string, remoteIP string) error {
- // 检查是否启用 Turnstile
- if !s.settingService.IsTurnstileEnabled(ctx) {
- logger.LegacyPrintf("service.turnstile", "%s", "[Turnstile] Disabled, skipping verification")
- return nil
- }
- // 获取 Secret Key
- secretKey := s.settingService.GetTurnstileSecretKey(ctx)
- return s.VerifyTokenWithSecret(ctx, secretKey, token, remoteIP)
- }
- func (s *TurnstileService) VerifyTokenWithSecret(ctx context.Context, secretKey, token, remoteIP string) error {
- if secretKey == "" {
- logger.LegacyPrintf("service.turnstile", "%s", "[Turnstile] Secret key not configured")
- return ErrTurnstileNotConfigured
- }
- // 如果 token 为空,返回错误
- if token == "" {
- logger.LegacyPrintf("service.turnstile", "%s", "[Turnstile] Token is empty")
- return ErrTurnstileVerificationFailed
- }
- logger.LegacyPrintf("service.turnstile", "[Turnstile] Verifying token for IP: %s", remoteIP)
- if s == nil || s.verifier == nil {
- return ErrTurnstileNotConfigured
- }
- result, err := s.verifier.VerifyToken(ctx, secretKey, token, remoteIP)
- if err != nil {
- logger.LegacyPrintf("service.turnstile", "[Turnstile] Request failed: %v", err)
- return fmt.Errorf("send request: %w", err)
- }
- if !result.Success {
- logger.LegacyPrintf("service.turnstile", "[Turnstile] Verification failed, error codes: %v", result.ErrorCodes)
- return ErrTurnstileVerificationFailed
- }
- logger.LegacyPrintf("service.turnstile", "%s", "[Turnstile] Verification successful")
- return nil
- }
- // IsEnabled 检查 Turnstile 是否启用
- func (s *TurnstileService) IsEnabled(ctx context.Context) bool {
- return s.settingService.IsTurnstileEnabled(ctx)
- }
- // ValidateSecretKey 验证 Turnstile Secret Key 是否有效
- func (s *TurnstileService) ValidateSecretKey(ctx context.Context, secretKey string) error {
- // 发送一个测试token的验证请求来检查secret_key是否有效
- result, err := s.verifier.VerifyToken(ctx, secretKey, "test-validation", "")
- if err != nil {
- return fmt.Errorf("validate secret key: %w", err)
- }
- // 检查是否有 invalid-input-secret 错误
- for _, code := range result.ErrorCodes {
- if code == "invalid-input-secret" {
- return ErrTurnstileInvalidSecretKey
- }
- }
- // 其他错误(如 invalid-input-response)说明 secret key 是有效的
- return nil
- }
|