分享个人 Full-Stack JavaScript 项目开发经验
本文介绍 Google 的 reCAPTCHA v2 中的“进行人机身份验证”复选框的应用例子。
首先,我们需要使用谷歌账号登录 https://www.google.com/recaptcha/admin,填写网站域名和标签相关信息。然后在 reCAPTCHA 类型中选择“进行人机身份验证”复选框。最后谷歌会为你生成两个密钥。一个是你的网站提供给用户的 HTML 代码中使用的网站密钥,另一个为你的网站服务器端和 reCAPTCHA 之间的通信密钥。
html
<form>
<div id="recaptcha" class="g-recaptcha"></div>
<button id="signIn" class="btn btn-lg btn-default btn-block" disabled type="button">登录</button>
</form>
<script src="/index.js"></script>
<script src="https://www.recaptcha.net/recaptcha/api.js?onload=onloadCallback&render=explicit"></script>
这里选择显式渲染 reCAPTCHA,以便可以控制在登录失败一次后再要求用户证明自己不是机器人。
表单中使用固定类名 g-recaptcha 的 div 作为 reCAPTCHA 的渲染容器。最后一个 script 标签加载 reCAPTCHA 的相关脚本。其中参数 onload 用于定义加载完毕时调用的函数名称,这里的 onloadCallback 回调函数放在更先加载 index.js 中。参数 render 值为 explicit 代表要求显式地渲染,而不是 onload 时找到 g-recaptcha 标签然后渲染。
index.js
var widgetId;
function onloadCallback() {
// 显式渲染 reCAPTCHA
widgetId = grecaptcha.render('recaptcha', {sitekey: 'your_sitekey'});
$('#signIn').prop('disabled', false);
}
function submit(){
// 获取响应结果,需要把结果发送给后台
var recaptcha = grecaptcha.getResponse(widgetId);
......
// 后台验证失败时,重置 reCAPTCHA
grecaptcha.reset(widgetId);
}
在服务器端接收客户端的 reCAPTCHA 响应,并请求验证结果。下面以 koa2 作为服务器端框架,介绍这个过程:
const https = require("https");
const querystring = require('querystring');
module.exports = async (ctx, next) => {
// ......
const {recaptcha} = ctx.request.body;
// reCAPTCHA 认证
const verifyCaptcha = function () {
return new Promise((resolve, reject) => {
const verify_data = querystring.stringify({
secret: 'your_secret',
response: recaptcha
});
const post_req = https.request({
host: 'recaptcha.net',
path: '/recaptcha/api/siteverify',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-length': verify_data.length
}
}, function (res) {
let dataArray = [];
let size = 0;
res.on('data', function (data) {
dataArray.push(data);
size += data.length;
});
res.on('end', function () {
const buff = Buffer.concat(dataArray, size);
const result = buff.toString('utf8');
resolve(result);
});
});
// 发送数据
post_req.write(verify_data);
post_req.end();
})
};
const captchaResponse = await verifyCaptcha();
console.log(JSON.parse(captchaResponse));
}
接口响应的 JSON 对象格式如下:
{
"success": true|false,
"challenge_ts": timestamp, // 查询时间 (yyyy-MM-dd'T'HH:mm:ssZZ)
"hostname": string, // 请求 reCAPTCHA 的主机名
"error-codes": [...] // 错误代码
}
这样,我们就可以利用人机验证结果作响应处理。
注意,如何你的网站设置了内容安全策略,需要在 script-src 和 child-src 中放行 https://www.recaptcha.net 和 https://www.gstatic.cn。
要了解更多更新的 reCAPTCHA 介绍,请点击这里。