/
checker_recaptcha.go
70 lines (59 loc) · 1.51 KB
/
checker_recaptcha.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package captcha
import (
"fmt"
"io"
"net/http"
"net/url"
"time"
"github.com/ArtalkJS/Artalk/internal/config"
"github.com/tidwall/gjson"
)
const RECAPTCHA_API = "https://www.google.com/recaptcha/api/siteverify"
var _ Checker = (*ReCaptchaChecker)(nil)
type ReCaptchaChecker struct {
User *User
SiteKey string
SecreteKey string
}
func NewReCaptchaChecker(conf *config.ReCaptchaConf, user *User) *ReCaptchaChecker {
return &ReCaptchaChecker{
User: user,
SiteKey: conf.SiteKey,
SecreteKey: conf.SecretKey,
}
}
func (c *ReCaptchaChecker) Check(value string) (bool, error) {
// 构建 POST 请求的参数
values := make(url.Values)
values.Add("secret", c.SecreteKey)
values.Add("response", value)
if c.User.IP != "" {
values.Add("remoteip", c.User.IP)
}
// 发送 POST 请求
url := RECAPTCHA_API
cli := http.Client{Timeout: time.Second * 10} // 10s 超时
resp, err := cli.PostForm(url, values)
if err != nil || resp.StatusCode != 200 {
return false, err
}
defer resp.Body.Close()
// 解析响应内容
respBuf, _ := io.ReadAll(resp.Body)
success := gjson.GetBytes(respBuf, "success")
if success.Exists() && success.Bool() {
// 验证成功
return true, nil
} else {
// 验证失败
return false, fmt.Errorf("err reason: %s", gjson.GetBytes(respBuf, "error-codes").String())
}
}
func (c *ReCaptchaChecker) Type() CaptchaType {
return IFrame
}
func (c *ReCaptchaChecker) Get() ([]byte, error) {
return RenderIFrame("recaptcha.html", Map{
"site_key": c.SiteKey,
})
}