Skip to content

Go Server SDK

官方 Go 伺服器端 SDK — github.com/Captcha-La/captchala-go

SDK 為您處理三項任務:

  1. 驗證(Validate) — 校驗來自瀏覽器 SDK 的 pt_ pass token。
  2. 簽發(Issue) — 簽發一次性 sct_ server token,將即將發起的 challenge 綁定到特定 action / IP / UID。
  3. 內容審核(Moderate) — 多模態(文字 + 圖片)內容審核,與控制台共用同一條 OpenAI 相容管線。

安裝

bash
go get github.com/Captcha-La/captchala-go

僅使用標準函式庫,無外部相依。

驗證(pt_ token)

請傳入終端使用者的 IP(從 CF-Connecting-IP / X-Forwarded-For 取得, 並回退至 RemoteAddr)。為選填,但建議帶上 — 它會用於額外的風險檢查。

go
import captchala "github.com/Captcha-La/captchala-go"

client := captchala.NewClient(appKey, appSecret)

func handler(w http.ResponseWriter, r *http.Request) {
    token := r.FormValue("captcha_token")

    result, err := client.ValidateWithClientIP(token, false, clientIP(r))
    if err != nil || !result.Valid {
        http.Error(w, result.Error, http.StatusBadRequest)
        return
    }
    // Verification passed; proceed with the request.
    // result.CaptchaArgs has Platform / UserIP / Referer / Pkg / SolvedAt / RiskScore
}

// Real end-user IP behind a CDN / proxy
func clientIP(r *http.Request) string {
    if ip := r.Header.Get("CF-Connecting-IP"); ip != "" {
        return ip
    }
    if xff := r.Header.Get("X-Forwarded-For"); xff != "" {
        return strings.TrimSpace(strings.Split(xff, ",")[0])
    }
    host, _, _ := net.SplitHostPort(r.RemoteAddr)
    return host
}

手邊沒有 IP?改用 client.Validate(token) — 驗證照常運作,只是少了基於 IP 的額外風險訊號。

若原始 server_token 簽發時帶有 bind_uid,請進行比對:

go
if result.UID != expectedUserID {
    http.Error(w, "user mismatch", http.StatusBadRequest)
    return
}

該次解題的環境資訊也會在 result.CaptchaArgs 中回傳,供您參考:

go
ip := result.CaptchaArgs.UserIP   // visitor IP recorded at solve time

簽發 server token

建議用於高價值流程(登入、註冊、支付):後端簽發一次性 sct_ token,交給瀏覽器,瀏覽器作為 serverToken prop 使用。 單次使用、限定 action,必要時可綁定 IP / UID。

go
issue, err := client.IssueServerTokenWithOptions("login", captchala.IssueOptions{
    BindingIP: userIP,    // backend rejects token if a different IP redeems it
    TTL:       300,       // seconds
    MaxUses:   5,         // SDK retry budget
    BindUID:   userID,    // pair with ValidateResult.UID on verify
})
if err != nil || !issue.OK {
    http.Error(w, issue.Error, http.StatusBadRequest)
    return
}
// hand issue.Token to the browser

僅使用預設值的快捷寫法:

go
issue, err := client.IssueServerToken("login")

內容審核

多模態 — 接受 ModerationItem 切片(OpenAI 相容格式的 text 與/或 image_url):

go
result, err := client.ModerationCheck([]captchala.ModerationItem{
    captchala.TextItem(userComment),
    captchala.ImageURLItem(uploadedImageURL),
}, userID)

if err != nil || !result.OK {
    http.Error(w, result.Error, http.StatusBadRequest)
    return
}

if result.Flagged {
    if result.HasCategory("violence", "csam") {
        // hard block
    }
}

純文字快捷寫法:

go
result, err := client.ModerationText("user comment here", userID)

分類由模型動態定義;請以遍歷 result.Categories 的方式防禦性處理,而非寫死固定集合。

型別

型別欄位
ValidateResultValidErrorUIDChallengeIDActionOfflineClientOnlyWarningCaptchaArgs
CaptchaArgs(資訊性)PlatformUserIPRefererPkgSolvedAtRiskScore
IssueResultOKTokenExpiresInIssuedAtErrorMessage
IssueOptionsBindingIPTTLMaxUsesBindUID
ModerationItemTypeTextImageURL(請使用 TextItem() / ImageURLItem() 輔助函式)
ModerationResultOKFlaggedCategoriesContentTypeRawErrorMessage;方法 HasCategory(...names)

相關連結

MIT-licensed examples · CaptchaLa is operated independently