Skip to content

Go Server SDK

공식 Go 서버 측 SDK입니다 — github.com/Captcha-La/captchala-go.

SDK가 대신 처리해 주는 세 가지 작업:

  1. Validate — 브라우저 SDK에서 받은 pt_ pass token 을 검증합니다.
  2. Issue — 다가올 챌린지를 특정 액션 / IP / UID 에 바인딩하는 일회용 sct_ server token 을 발급합니다.
  3. Moderate — 대시보드가 사용하는 동일한 OpenAI 호환 파이프라인을 통한 멀티모달(텍스트 + 이미지) 콘텐츠 모더레이션을 수행합니다.

설치

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

표준 라이브러리만 사용합니다. 외부 의존성이 없습니다.

Validate (pt_ 토큰)

최종 사용자의 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_tokenbind_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_ 토큰을 발급하여 브라우저에 전달하고, 브라우저는 이를 serverToken prop 으로 사용합니다. 단일 사용, 액션 한정이며 선택적으로 IP/UID 에 바인딩됩니다.

go
issue, err := client.IssueServerTokenWithOptions("login", captchala.IssueOptions{
    BindingIP: userIP,    // 다른 IP가 토큰을 사용하면 백엔드가 거부합니다
    TTL:       300,       // 초
    MaxUses:   5,         // SDK 재시도 예산
    BindUID:   userID,    // 검증 시 ValidateResult.UID 와 매칭
})
if err != nil || !issue.OK {
    http.Error(w, issue.Error, http.StatusBadRequest)
    return
}
// issue.Token 을 브라우저로 전달합니다

기본값 전용 단축 메서드:

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

콘텐츠 모더레이션

멀티모달 — ModerationItem 슬라이스(OpenAI 호환 형식의 텍스트 및/또는 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") {
        // 강제 차단
    }
}

순수 텍스트용 단축 메서드:

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

카테고리는 모델이 정의합니다. 고정된 집합을 하드코딩하는 대신 result.Categories 를 방어적으로 순회하십시오.

타입

TypeFields
ValidateResultValid, Error, UID, ChallengeID, Action, Offline, ClientOnly, Warning, CaptchaArgs
CaptchaArgs (참고용)Platform, UserIP, Referer, Pkg, SolvedAt, RiskScore
IssueResultOK, Token, ExpiresIn, IssuedAt, Error, Message
IssueOptionsBindingIP, TTL, MaxUses, BindUID
ModerationItemType, Text, ImageURL (TextItem() / ImageURLItem() 헬퍼 사용)
ModerationResultOK, Flagged, Categories, ContentType, Raw, Error, Message; 메서드 HasCategory(...names)

링크

MIT-licensed examples · CaptchaLa is operated independently