腾讯防水墙验证码使用

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

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

功能也比较丰富,支持:

  • 2000次/小时安全防护

  • 支持免验证+分级验证

  • 三分钟快速接入

  • 全功能配置后台

  • 支持HTTPS

  • 阈值内流量无广告

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

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

0.前端页面

在 HTML 中引入js文件:

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

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

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

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

然后注册回调函数:

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

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

<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>

修改回调函数:

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.后端

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

如下:

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 即表示此次请求是“正常”的。

总结

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

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

整体还不错。