详细内容参考hCaptcha官方文档:https://docs.hcaptcha.com/
本文可作为教程和文档的补充。
使用hCaptcha前需要注册账号,注册完成后,会得到两个令牌
-
一个令牌叫site key,是32个字符的uuid。site key放在前端,也就是需要插入到显示验证码的网页上,因此是可以公开的。
-
另一个令牌叫Secret Key,是40位的16进制数。Secret Key放在后端,不可公开。
部署hCaptcha分两步:
-
在网页上插入hCaptcha控件,这段代码负责显示hcaptcha控件。比如说你希望在个人博客的评论区上添加验证码,就把这个控件放到发布按钮附近。
-
在服务器代码上部署后端验证代码,这段代码会把用户的验证码递交给hcaptcha服务器。比如你希望别人发布评论的时候填写验证码,就把后端验证代码添加进发布评论的逻辑里。
在hcaptcha验证过程中,存在三方:用户(填写验证码的人)、网站服务器(你要部署hcaptcha的服务器)、和hcaptcha的官方服务器。hcaptcha的工作流程是:
-
用户填写验证码;
-
验证码上传到网站服务器上,上传的内容称为Response;
-
网站服务器把Response和自己的Secret Key一起打包,发送给hcaptcha的官方服务器;
-
hcaptcha的官方服务器把验证结果发送给网站服务器;
-
网站服务器根据验证结果,决定是否放行。
-
在网页上插入hCaptcha控件
1.1 首先在网页上引入hcaptcha脚本:
<scri src="https://js.hcaptcha.com/1/api.js" async defer></scri>
1.2 然后在欲展示验证码的位置,插入以下html
<diw class="h-captcha" data-sitekey="your_site_key"></diw>
(这里把script写作scri,div写作diw,防止被WAF拦截)
这里可以随意插入html,但必须满足以下三个要求:
- 必须包含“h-captcha”的类名;
- 必须包含“data-sitekey”的属性,属性值是你的site key;
- html内部必须是空值(在这里,div块之间不能有内容)
做完以上两步后,hcaptcha脚本就会自动在你的网页中插入验证码控件了,无需其它操作。
- 在后端引入hCaptcha验证
2.1 在用户提交请求时,携带Response
这需要修改提交请求的表单,因后端程序不同而异。
2.2 向hcaptcha服务器发起请求。
现在,后端需要打包Response和secret key,向hcaptcha服务器发起请求。
不同的后端语言,发起请求的方式不同,官方给出的例子是curl:
curl https://hcaptcha.com/siteverify \
-X POST \
-d "response=CLIENT-RESPONSE&secret=YOUR-SECRET"
hcaptcha的官方服务器返回的是json,取里面的“success”字段,如果是true,即为通过,反之不通过。
Python的例子如下(使用request)
def verify(secret, response) -> bool:
# 用request发起post请求,表单数据里有secret和response两个字段
r = requests.post('https://hcaptcha.com/siteverify', data={
'secret': secret,
'response': response
})
# 从json里读取success字段
valid = json.loads(r.text).get('success')
if valid:
return True
else:
return False
Rust语言的例子如下(使用Reqwest)
/// response: 前端提交的验证码
/// secret: secret key,需要保密
pub async fn verify_captcha(response: &str, secret: &str) -> Result<bool, std::io::Error> {
use serde_derive::Deserialize;
#[derive(Deserialize)]
struct Response {
success: bool,
challenge_ts: String,
hostname: String,
error_codes: Option<Vec<String>>,
}
const URL: &str = "https://hcaptcha.com/siteverify";
let form = [("response", response), ("secret", secret)];
let client = reqwest::ClientBuilder::new().build()?;
match client.post(URL).form(&form).send().await {
Ok(resp) if resp.status().as_u16() == 200 => match resp.json::<Response>().await {
Ok(r) if r.success => Ok(true),
_ => Ok(false),
},
_ => Ok(false),
}
}
在后端逻辑中加上上述的“verify”函数,就可以使用hcaptcha验证码了。