Skip to content

Import path: gitlab.soludian.com/soludian/fountain/libs/resilient/recaptcha

recaptcha

go
import "gitlab.soludian.com/soludian/fountain/libs/resilient/recaptcha"

Package recaptcha là verifier dùng chung cho Google reCAPTCHA v2/v3, hCaptcha và Cloudflare Turnstile — cả ba provider chia sẻ cùng schema `secret + response (+remoteip)` siteverify nên một verifier xử lý hết.

Theo chuẩn lib_3rd của Fountain — install qua config.yaml:

# config.yaml
recaptcha:
  enabled: true
  secret_key: "${RECAPTCHA_SECRET}"
  min_score: 0.5

// code
v := recaptcha.InstallFountainInstance()
if err := v.Verify(ctx, token, recaptcha.ActionLogin, ip); err != nil { ... }

Hoặc dựng instance ad-hoc qua options (không cần config.yaml):

v := recaptcha.InstallFountainInstance(
    recaptcha.WithEnabled(true),
    recaptcha.WithSecretKey(secret),
    recaptcha.WithMinScore(0.5),
)

Index

Constants

Action labels — khớp với param `action` của reCAPTCHA v3 ở client. Caller có thể tự định nghĩa action khác; chỉ cần khớp với cfg.Actions (nếu set).

go
const (
    ActionLogin         = "login"
    ActionRegister      = "register"
    ActionPasswordReset = "password_reset"
)

DefaultSiteVerifyURL là endpoint Google reCAPTCHA. Đổi qua Config.SiteVerifyURL để dùng provider khác:

go
const DefaultSiteVerifyURL = "https://www.google.com/recaptcha/api/siteverify"

DefaultTimeout giới hạn thời gian gọi siteverify — fail-closed nếu provider chậm. Caller thà block còn hơn để user chờ vô hạn.

go
const DefaultTimeout = 5 * time.Second

go
const KPackageName = "recaptcha"

Variables

Sentinel errors cho phép caller phân nhánh chính xác bằng errors.Is.

go
var (
    ErrMisconfigured    = errors.New("recaptcha: misconfigured")
    ErrMissingToken     = errors.New("recaptcha: token is required")
    ErrUnreachable      = errors.New("recaptcha: provider unreachable")
    ErrInvalidResponse  = errors.New("recaptcha: invalid provider response")
    ErrRejected         = errors.New("recaptcha: provider rejected token")
    ErrLowScore         = errors.New("recaptcha: score below threshold")
    ErrActionMismatch   = errors.New("recaptcha: action mismatch")
    ErrHostnameMismatch = errors.New("recaptcha: hostname not allowed")
)

go
var GetFountainInstance = Lib.GetFountainInstance

go
var GetFountainInstanceNames = Lib.GetFountainInstanceNames

go
var GetFountainManager = Lib.GetFountainManager

Sử dụng khi config instance ở dạng key:value; Nếu config instance ở dạng key:array thì sử dụng hàm InstallFountainInstances

Install with config format <key>:<value>; eg: recaptcha:<value>

Usage:

# config.yaml
recaptcha:
  enabled: true
  secret_key: "..."
  min_score: 0.5

# code.go
v := recaptcha.InstallFountainInstance()

Hoặc đổi config key:

v := recaptcha.WithConfigKey("captcha_login").InstallFountainInstance()
go
var InstallFountainInstance = Lib.InstallFountainInstance

Sử dụng khi config instance ở dạng key:array<value>; Sẽ luôn cố gắng khởi tạo kể cả khi config ở dạng key:value

Install with config format <key>:array<value>; eg: recaptcha:array<value>

Usage:

# config.yaml
recaptcha:
  - name: login
    enabled: true
    secret_key: "..."
  - name: register
    enabled: true
    secret_key: "..."
    min_score: 0.7

# code.go
recaptcha.InstallFountainInstances()
v := recaptcha.GetFountainInstance("login")
go
var InstallFountainInstances = Lib.InstallFountainInstances

Truy cập thẳng tới bộ quản lý thư viện

go
var Lib = lib_3rd.NewLib(newClient, lib_3rd.WithDefaultConfigFunc[Config, Verifier](DefaultConfig))

go
var WithConfigKey = Lib.WithConfigKey

func WithActions

go
func WithActions(actions ...string) lib_3rd.Option[Config]

WithActions giới hạn action label hợp lệ (chỉ áp cho v3 khi response.action có giá trị). Rỗng = không kiểm tra.

func WithConfig

go
func WithConfig(conf *Config) lib_3rd.Option[Config]

WithConfig copy mọi field từ conf sang config target. Dùng khi caller đã có sẵn Config object (vd build từ env hoặc remote config service).

func WithEnabled

go
func WithEnabled(enabled bool) lib_3rd.Option[Config]

WithEnabled bật/tắt verifier. False → Verify trả nil ngay không gọi provider.

func WithEnvironment

go
func WithEnvironment(env string) lib_3rd.Option[Config]

WithEnvironment đặt environment label cho config (production/staging/...).

func WithHostnames

go
func WithHostnames(hostnames ...string) lib_3rd.Option[Config]

WithHostnames giới hạn hostname client hợp lệ — ngăn token bị reuse từ site khác. Rỗng = không kiểm tra.

func WithMinScore

go
func WithMinScore(score float64) lib_3rd.Option[Config]

WithMinScore đặt ngưỡng score cho reCAPTCHA v3 (0..1). 0 = bỏ qua. Khuyến nghị 0.5 cho login, 0.7 cho register / password reset.

func WithName

go
func WithName(name string) lib_3rd.Option[Config]

WithName đặt tên instance — dùng khi nhiều instance cùng config key.

func WithSecretKey

go
func WithSecretKey(secret string) lib_3rd.Option[Config]

WithSecretKey đặt secret key của Google reCAPTCHA / hCaptcha / Turnstile. BẮT BUỘC khi Enabled=true.

func WithSiteVerifyURL

go
func WithSiteVerifyURL(url string) lib_3rd.Option[Config]

WithSiteVerifyURL đổi endpoint siteverify để dùng provider khác:

func WithTimeout

go
func WithTimeout(timeout time.Duration) lib_3rd.Option[Config]

WithTimeout đặt timeout cho mỗi lần gọi siteverify. <= 0 → DefaultTimeout.

type Config

Config là cấu hình một instance Verifier — bind từ config.yaml qua key `recaptcha:` (hoặc key tuỳ chỉnh truyền vào WithConfigKey).

# config.yaml
recaptcha:
  name: default
  enabled: true
  secret_key: "${RECAPTCHA_SECRET}"
  min_score: 0.5            # chỉ áp cho v3
  hostnames: ["app.example.com"]
  actions:   ["login", "register"]
  timeout:   5s
go
type Config struct {
    lib_3rd.BaseConfig `conf:",squash"`

    // Enabled: master switch. False → Verifier.Verify trả về nil ngay không
    // gọi provider (no-op cho dev / incident toggle).
    Enabled bool `conf:"enabled" json:"enabled"`

    // SecretKey: secret server-side của Google reCAPTCHA / hCaptcha / Turnstile.
    // BẮT BUỘC khi Enabled=true.
    SecretKey string `conf:"secret_key" json:"secret_key"`

    // MinScore (chỉ v3): score tối thiểu được pass. 0 = bỏ qua kiểm tra.
    // Khuyến nghị 0.5 cho login, 0.7 cho register / password reset. Provider
    // v2 / hCaptcha v1 không trả score → bỏ qua dù MinScore > 0.
    MinScore float64 `conf:"min_score" json:"min_score"`

    // Hostnames (optional): danh sách hostname client hợp lệ. Rỗng = không
    // kiểm tra. Set để ngăn token bị reuse từ site khác.
    Hostnames []string `conf:"hostnames" json:"hostnames"`

    // Actions (optional): nếu set, response.action phải nằm trong list (HOẶC
    // khớp với param action truyền vào Verify nếu khác rỗng).
    Actions []string `conf:"actions" json:"actions"`

    // SiteVerifyURL: endpoint siteverify. Rỗng → DefaultSiteVerifyURL (Google).
    SiteVerifyURL string `conf:"site_verify_url" json:"site_verify_url"`

    // Timeout: giới hạn mỗi lần gọi siteverify. <= 0 → DefaultTimeout.
    Timeout time.Duration `conf:"timeout" json:"timeout"`
}

func DefaultConfig

go
func DefaultConfig() *Config

func (*Config) GetName

go
func (c *Config) GetName() string

func (*Config) Validate

go
func (conf *Config) Validate() error

Validate điền giá trị mặc định và kiểm tra config có khả dụng không. Nếu Enabled=true mà SecretKey rỗng → panic để admin phát hiện sớm. Khi Enabled=false (toggle off), Validate không check SecretKey để dev local chỉ cần `enabled: false` trong config.yaml.

type Verifier

Verifier là instance được lib_3rd quản lý. Tạo qua InstallFountainInstance (theo config.yaml) hoặc qua options. Thread-safe — gọi Verify từ nhiều goroutine OK.

go
type Verifier struct {
    // contains filtered or unexported fields
}

func (*Verifier) Config

go
func (v *Verifier) Config() *Config

Config trả về snapshot config (read-only — modify không có tác dụng).

func (*Verifier) IsEnabled

go
func (v *Verifier) IsEnabled() bool

IsEnabled trả về true nếu instance này active — caller có thể check để render widget có điều kiện.

func (*Verifier) Verify

go
func (v *Verifier) Verify(ctx context.Context, token, action, remoteIP string) error

Verify gọi siteverify và validate response. Trả nil khi pass HOẶC khi Verifier disabled (Enabled=false → no-op để toggle nhanh trong incident).

Dùng errors.Is để phân nhánh:

if err := v.Verify(ctx, token, recaptcha.ActionLogin, ip); err != nil {
    switch {
    case errors.Is(err, recaptcha.ErrMissingToken):    // ép client gửi token
    case errors.Is(err, recaptcha.ErrLowScore):        // step-up auth
    case errors.Is(err, recaptcha.ErrUnreachable):     // fail-closed log
    default:                                            // generic block
    }
}

ctx: nếu deadline / cancellation kích hoạt, Verify trả ErrUnreachable kèm nguyên nhân gốc.

Generated by gomarkdoc