Import path:
gitlab.soludian.com/soludian/fountain/libs/resilient/recaptcha
recaptcha
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
- Variables
- func WithActions(actions ...string) lib_3rd.Option[Config]
- func WithConfig(conf *Config) lib_3rd.Option[Config]
- func WithEnabled(enabled bool) lib_3rd.Option[Config]
- func WithEnvironment(env string) lib_3rd.Option[Config]
- func WithHostnames(hostnames ...string) lib_3rd.Option[Config]
- func WithMinScore(score float64) lib_3rd.Option[Config]
- func WithName(name string) lib_3rd.Option[Config]
- func WithSecretKey(secret string) lib_3rd.Option[Config]
- func WithSiteVerifyURL(url string) lib_3rd.Option[Config]
- func WithTimeout(timeout time.Duration) lib_3rd.Option[Config]
- type Config
- type Verifier
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).
const (
ActionLogin = "login"
ActionRegister = "register"
ActionPasswordReset = "password_reset"
)DefaultSiteVerifyURL là endpoint Google reCAPTCHA. Đổi qua Config.SiteVerifyURL để dùng provider khác:
- Google reCAPTCHA: https://www.google.com/recaptcha/api/siteverify (default)
- hCaptcha: https://api.hcaptcha.com/siteverify
- Turnstile: https://challenges.cloudflare.com/turnstile/v0/siteverify
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.
const DefaultTimeout = 5 * time.Secondconst KPackageName = "recaptcha"Variables
Sentinel errors cho phép caller phân nhánh chính xác bằng errors.Is.
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")
)var GetFountainInstance = Lib.GetFountainInstancevar GetFountainInstanceNames = Lib.GetFountainInstanceNamesvar GetFountainManager = Lib.GetFountainManagerSử 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()var InstallFountainInstance = Lib.InstallFountainInstanceSử 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")var InstallFountainInstances = Lib.InstallFountainInstancesTruy cập thẳng tới bộ quản lý thư viện
var Lib = lib_3rd.NewLib(newClient, lib_3rd.WithDefaultConfigFunc[Config, Verifier](DefaultConfig))var WithConfigKey = Lib.WithConfigKeyfunc WithActions
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
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
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
func WithEnvironment(env string) lib_3rd.Option[Config]WithEnvironment đặt environment label cho config (production/staging/...).
func WithHostnames
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
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
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
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
func WithSiteVerifyURL(url string) lib_3rd.Option[Config]WithSiteVerifyURL đổi endpoint siteverify để dùng provider khác:
- hCaptcha: https://api.hcaptcha.com/siteverify
- Turnstile: https://challenges.cloudflare.com/turnstile/v0/siteverify
func WithTimeout
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: 5stype 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
func DefaultConfig() *Configfunc (*Config) GetName
func (c *Config) GetName() stringfunc (*Config) Validate
func (conf *Config) Validate() errorValidate đ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.
type Verifier struct {
// contains filtered or unexported fields
}func (*Verifier) Config
func (v *Verifier) Config() *ConfigConfig trả về snapshot config (read-only — modify không có tác dụng).
func (*Verifier) IsEnabled
func (v *Verifier) IsEnabled() boolIsEnabled trả về true nếu instance này active — caller có thể check để render widget có điều kiện.
func (*Verifier) Verify
func (v *Verifier) Verify(ctx context.Context, token, action, remoteIP string) errorVerify 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