85 lines
1.9 KiB
Go
85 lines
1.9 KiB
Go
package service
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/xmdhs/authlib-skin/model"
|
|
)
|
|
|
|
func (w *WebService) GetConfig(ctx context.Context) model.Config {
|
|
return model.Config{
|
|
Captcha: model.Captcha{
|
|
Type: w.config.Captcha.Type,
|
|
SiteKey: w.config.Captcha.SiteKey,
|
|
},
|
|
ServerName: w.config.ServerName,
|
|
AllowChangeName: !w.config.OfflineUUID,
|
|
}
|
|
}
|
|
|
|
type turnstileRet struct {
|
|
Success bool `json:"success"`
|
|
ErrorCodes []string `json:"error-codes"`
|
|
}
|
|
|
|
var ErrCaptcha = errors.New("验证码错误")
|
|
|
|
type ErrTurnstile struct {
|
|
ErrorCodes []string
|
|
}
|
|
|
|
func (e ErrTurnstile) Error() string {
|
|
return strings.Join(e.ErrorCodes, " ")
|
|
}
|
|
|
|
func (w *WebService) verifyCaptcha(ctx context.Context, token, ip string) error {
|
|
if w.config.Captcha.Type != "turnstile" {
|
|
return nil
|
|
}
|
|
bw := &bytes.Buffer{}
|
|
err := json.NewEncoder(bw).Encode(turnstileResponse{
|
|
Secret: w.config.Captcha.Secret,
|
|
Response: token,
|
|
Remoteip: ip,
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("verifyTurnstile: %w", err)
|
|
}
|
|
reqs, err := http.NewRequestWithContext(ctx, "POST", "https://challenges.cloudflare.com/turnstile/v0/siteverify", bw)
|
|
if err != nil {
|
|
return fmt.Errorf("verifyTurnstile: %w", err)
|
|
}
|
|
reqs.Header.Set("Accept", "*/*")
|
|
reqs.Header.Set("Content-Type", "application/json")
|
|
rep, err := w.httpClient.Do(reqs)
|
|
if err != nil {
|
|
return fmt.Errorf("verifyTurnstile: %w", err)
|
|
}
|
|
defer rep.Body.Close()
|
|
|
|
var t turnstileRet
|
|
err = json.NewDecoder(rep.Body).Decode(&t)
|
|
if err != nil {
|
|
return fmt.Errorf("verifyTurnstile: %w", err)
|
|
}
|
|
|
|
if !t.Success {
|
|
return fmt.Errorf("verifyTurnstile: %w", errors.Join(ErrTurnstile{
|
|
ErrorCodes: t.ErrorCodes,
|
|
}, ErrCaptcha))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type turnstileResponse struct {
|
|
Secret string `json:"secret"`
|
|
Response string `json:"response"`
|
|
Remoteip string `json:"remoteip"`
|
|
}
|