腾讯防水墙验证码使用

前阵子腾讯出了个验证码产品,宣称“告别传统验证码的单点防御,十道安全栅栏打造立体全面的安全验证,将黑产拒之门外”。看起来很不错的样子,正好之前使用过另外一家类似的产品,但是当时没有试用,今天特地注册了解了一下。

注册很简单,填写手机号邮箱和域名等即可。由于是在本地环境测试,似乎填写的域名并没有什么影响。而且填写时可以选择适用场景,应该是针对不同的场景有不同的策略。

功能也比较丰富,支持:

  • 2000次/小时安全防护

  • 支持免验证+分级验证

  • 三分钟快速接入

  • 全功能配置后台

  • 支持HTTPS

  • 阈值内流量无广告

注册完之后会分配一个 appidApp Secret KeyApp Secret Key 需要妥善保存,不可暴露出来。

下面就简单的记录下普通场景下如何使用。(此场景指简单使用,非验证码配置的场景)

0.前端页面

在 HTML 中引入js文件:

1
<script src="https://ssl.captcha.qq.com/TCaptcha.js"></script>

然后在需要激活的位置加入:

1
2
3
4
<button id="TencentCaptcha"
data-appid="200700xxxx"
data-cbfn="callback"
>验证</button>

官方文档表示可以使用其他标签,只需有 idcbfn 属性即可。

然后注册回调函数:

1
2
3
4
5
6
7
8
window.callback = function(res){
console.log(res)
// res(未通过验证)= {ret: 1, ticket: null}
// res(验证成功) = {ret: 0, ticket: "String", randstr: "String"}
if(res.ret === 0){
alert(res.ticket) // 票据
}
}

前端的 callback 如果验证成功后,就可以在提交信息的同时把腾讯返回的内容提交给后端,主要是验证票据:ticket 和随机字符串:randstr

我测试的例子中是这样的:

1
2
3
4
5
6
<form action="/verify" method="post">
<input type="text" name="appid" value="200700xxxx"/>
<input type="text" id="ticket" name="ticket"/>
<input type="text" id="randstr" name="randstr"/>
<button id="btn" disabled>submit</button>
</form>

修改回调函数:

1
2
3
4
5
6
7
8
9
10
11
window.callback = function(res){
console.log(res)
if(res.ret === 0){
document.getElementById('ticket').value = res.ticket
document.getElementById('randstr').value = res.randstr
document.getElementById('ticket').value = res.ticket
document.getElementById('btn').disabled = false
} else {
alert('验证失败')
}
}

前端验证成功后,把 ticketrandstr 填充到表单中去。

此时页面就可以使用这个验证服务了。

1.后端

后端拿到提交的表单后,需要再去请求腾讯的接口验证是否成功。

如下:

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
func serveVerify(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Error(w, "Method not allowed", 405)
return
}
r.ParseForm()
aid := r.Form["appid"][0]
AppSecretKey := "yourSecretKey"
UserIP := r.RemoteAddr
Ticket := r.Form["ticket"][0]
Randstr := r.Form["randstr"][0]
req, err := http.NewRequest("GET", API, nil)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
q := req.URL.Query()
q.Add("aid", aid)
q.Add("AppSecretKey", AppSecretKey)
q.Add("UserIP", UserIP)
q.Add("Ticket", Ticket)
q.Add("Randstr", Randstr)
req.URL.RawQuery = q.Encode()
httpClient := &http.Client{
Timeout: 10*time.Second,
}
fmt.Println("going to check :",req.URL.String())
resp, err := httpClient.Do(req)
defer resp.Body.Close()
if err != nil {
w.Write([]byte("got error"))
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
w.Write([]byte("got error"))
}
w.Write(body)
}

腾讯服务器将返回 {response:1, evil_level:70, err_msg:""} 类似的内容。其中:

response = 1 表示验证成功。

evil_level 是恶意等级,范围为0-100。

response = 1 即表示此次请求是“正常”的。

总结

确实很容易接入,而且还提供了验证数据的请求统计等,包括通过与拦截的数据,日请求量,通过量,拦截量。

后台还提供了对场景更改的操作,也可以定制外观。

整体还不错。