分享个人 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() {// 显式渲染 reCAPTCHAwidgetId = grecaptcha.render('recaptcha', {sitekey: 'your_sitekey'});$('#signIn').prop('disabled', false);}function submit(){// 获取响应结果,需要把结果发送给后台var recaptcha = grecaptcha.getResponse(widgetId);......// 后台验证失败时,重置 reCAPTCHAgrecaptcha.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 介绍,请点击这里。