refactor(captcha): update Cap to 2.0.0 (#2573)

* refactor(captcha): update Cap backend to 2.0.0 API format

* feat(captcha): add Cap version config for 1.x/2.x compatibility

* fix(captcha): change Cap default version to 1.x for backward compatibility

* refactor(captcha): remove Cap 1.x compatibility, keep only 2.x support

* feat(captcha): update field names to Cap 2.0 standard - Site Key and Secret Key

* fix(captcha): update Cap field names in defaults configuration
pull/2499/merge
WittF 2025-06-26 14:58:58 +08:00 committed by GitHub
parent 3db522609e
commit 2500ebc6a4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 18 additions and 16 deletions

View File

@ -393,8 +393,8 @@ var DefaultSettings = map[string]string{
"captcha_turnstile_site_key": "", "captcha_turnstile_site_key": "",
"captcha_turnstile_site_secret": "", "captcha_turnstile_site_secret": "",
"captcha_cap_instance_url": "", "captcha_cap_instance_url": "",
"captcha_cap_key_id": "", "captcha_cap_site_key": "",
"captcha_cap_key_secret": "", "captcha_cap_secret_key": "",
"thumb_width": "400", "thumb_width": "400",
"thumb_height": "300", "thumb_height": "300",
"thumb_entity_suffix": "._thumb", "thumb_entity_suffix": "._thumb",

View File

@ -3,6 +3,12 @@ package middleware
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"io"
"net/http"
"net/url"
"strings"
"time"
"github.com/cloudreve/Cloudreve/v4/application/dependency" "github.com/cloudreve/Cloudreve/v4/application/dependency"
"github.com/cloudreve/Cloudreve/v4/pkg/logging" "github.com/cloudreve/Cloudreve/v4/pkg/logging"
"github.com/cloudreve/Cloudreve/v4/pkg/recaptcha" "github.com/cloudreve/Cloudreve/v4/pkg/recaptcha"
@ -11,11 +17,6 @@ import (
"github.com/cloudreve/Cloudreve/v4/pkg/setting" "github.com/cloudreve/Cloudreve/v4/pkg/setting"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/mojocn/base64Captcha" "github.com/mojocn/base64Captcha"
"io"
"net/http"
"net/url"
"strings"
"time"
) )
type req struct { type req struct {
@ -133,7 +134,7 @@ func CaptchaRequired(enabled func(c *gin.Context) bool) gin.HandlerFunc {
break break
case setting.CaptchaCap: case setting.CaptchaCap:
captchaSetting := settings.CapCaptcha(c) captchaSetting := settings.CapCaptcha(c)
if captchaSetting.InstanceURL == "" || captchaSetting.KeyID == "" || captchaSetting.KeySecret == "" { if captchaSetting.InstanceURL == "" || captchaSetting.SiteKey == "" || captchaSetting.SecretKey == "" {
l.Warning("Cap verification failed: missing configuration") l.Warning("Cap verification failed: missing configuration")
c.JSON(200, serializer.ErrWithDetails(c, serializer.CodeCaptchaError, "Captcha configuration error", nil)) c.JSON(200, serializer.ErrWithDetails(c, serializer.CodeCaptchaError, "Captcha configuration error", nil))
c.Abort() c.Abort()
@ -146,9 +147,10 @@ func CaptchaRequired(enabled func(c *gin.Context) bool) gin.HandlerFunc {
request2.WithHeader(http.Header{"Content-Type": []string{"application/json"}}), request2.WithHeader(http.Header{"Content-Type": []string{"application/json"}}),
) )
capEndpoint := strings.TrimSuffix(captchaSetting.InstanceURL, "/") + "/" + captchaSetting.KeyID + "/siteverify" // Cap 2.0 API format: /{siteKey}/siteverify
capEndpoint := strings.TrimSuffix(captchaSetting.InstanceURL, "/") + "/" + captchaSetting.SiteKey + "/siteverify"
requestBody := map[string]string{ requestBody := map[string]string{
"secret": captchaSetting.KeySecret, "secret": captchaSetting.SecretKey,
"response": service.Ticket, "response": service.Ticket,
} }
requestData, err := json.Marshal(requestBody) requestData, err := json.Marshal(requestBody)

View File

@ -669,8 +669,8 @@ func (s *settingProvider) TurnstileCaptcha(ctx context.Context) *Turnstile {
func (s *settingProvider) CapCaptcha(ctx context.Context) *Cap { func (s *settingProvider) CapCaptcha(ctx context.Context) *Cap {
return &Cap{ return &Cap{
InstanceURL: s.getString(ctx, "captcha_cap_instance_url", ""), InstanceURL: s.getString(ctx, "captcha_cap_instance_url", ""),
KeyID: s.getString(ctx, "captcha_cap_key_id", ""), SiteKey: s.getString(ctx, "captcha_cap_site_key", ""),
KeySecret: s.getString(ctx, "captcha_cap_key_secret", ""), SecretKey: s.getString(ctx, "captcha_cap_secret_key", ""),
} }
} }

View File

@ -50,8 +50,8 @@ type Turnstile struct {
type Cap struct { type Cap struct {
InstanceURL string InstanceURL string
KeyID string SiteKey string
KeySecret string SecretKey string
} }
type SMTP struct { type SMTP struct {

View File

@ -30,7 +30,7 @@ type SiteConfig struct {
CaptchaType setting.CaptchaType `json:"captcha_type,omitempty"` CaptchaType setting.CaptchaType `json:"captcha_type,omitempty"`
TurnstileSiteID string `json:"turnstile_site_id,omitempty"` TurnstileSiteID string `json:"turnstile_site_id,omitempty"`
CapInstanceURL string `json:"captcha_cap_instance_url,omitempty"` CapInstanceURL string `json:"captcha_cap_instance_url,omitempty"`
CapKeyID string `json:"captcha_cap_key_id,omitempty"` CapSiteKey string `json:"captcha_cap_site_key,omitempty"`
RegisterEnabled bool `json:"register_enabled,omitempty"` RegisterEnabled bool `json:"register_enabled,omitempty"`
TosUrl string `json:"tos_url,omitempty"` TosUrl string `json:"tos_url,omitempty"`
PrivacyPolicyUrl string `json:"privacy_policy_url,omitempty"` PrivacyPolicyUrl string `json:"privacy_policy_url,omitempty"`
@ -137,7 +137,7 @@ func (s *GetSettingService) GetSiteConfig(c *gin.Context) (*SiteConfig, error) {
TurnstileSiteID: settings.TurnstileCaptcha(c).Key, TurnstileSiteID: settings.TurnstileCaptcha(c).Key,
ReCaptchaKey: reCaptcha.Key, ReCaptchaKey: reCaptcha.Key,
CapInstanceURL: capCaptcha.InstanceURL, CapInstanceURL: capCaptcha.InstanceURL,
CapKeyID: capCaptcha.KeyID, CapSiteKey: capCaptcha.SiteKey,
AppPromotion: appSetting.Promotion, AppPromotion: appSetting.Promotion,
}, nil }, nil
} }