如何为 PHP 表单添加 reCAPTCHAv3 支持
后知后觉 现有 3 评论

最新的 reCAPTCHAv3 版本不再需要用户进行交互(点选图像等),可以根据 AI 学习判断用户是否为真人,降低用户的操作成本。本文演示一个简单的示例为 PHP 表单添加 reCAPTCHAv3 支持。

令牌

首先需要去 Google reCAPTCHA 官网申请密钥和令牌。至于如何访问问题不再说明,自行处理。

原理

原理图(!AVIF)

简单说就是将谷歌的组件包含在网站里,然后用户提交表单时携带谷歌生成的令牌和站长的密钥,传输给谷歌服务器,然后谷歌服务器给返回一个数组,其中包含用户的真实程度。

以下是返回 JSON 的一个示例:

{
  "success": true|false,      // whether this request was a valid reCAPTCHA token for your site
  "score": number             // the score for this request (0.0 - 1.0)
  "action": string            // the action name for this request (important to verify)
  "challenge_ts": timestamp,  // timestamp of the challenge load (ISO format yyyy-MM-dd'T'HH:mm:ssZZ)
  "hostname": string,         // the hostname of the site where the reCAPTCHA was solved
  "error-codes": [...]        // optional
}
KeyDescription
success状态描述
score分数(分数越高真人程度越高)
action动作
challenge_ts时间戳

示例

在这节我们来创建一个示例文件,在此需要创建两个文件 subscribe_newsletter_form.php 和subscribe_newsletter_submit.php :

  • subscription_newsletter_form.php 文件用于显示新闻通讯订阅表单,该表单允许用户输入电子邮件地址并订阅新闻通讯。
  • subscription_newsletter_submit.php 文件处理表单提交并进行必要的验证。

创建时事通讯订阅表单

创建一个 subscribe_newsletter_form.php 示例表单文件

<html>
  <head>
    <title>Subscribe to Newsletter</title>
    <script
      src="https://code.jquery.com/jquery-3.4.1.min.js"
      integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
      crossorigin="anonymous"></script>
 
    <script src="https://www.google.com/recaptcha/api.js?render=6LdLk7EUAAAAAEWHuB2tabMmlxQ2-RRTLPHEGe9Y"></script>
  </head>
  <body>
    <div>
      <b>Subscribe Newsletter</b>
    </div>
 
    <form id="newsletterForm" action="subscribe_newsletter_submit.php" method="post">
      <div>
          <div>
              <input type="email" id="email" name="email">
          </div>
          <div>
              <input type="submit" value="submit">
          </div>
      </div>
    </form>
 
    <script>
    $('#newsletterForm').submit(function(event) {
        event.preventDefault();
        var email = $('#email').val();
 
        grecaptcha.ready(function() {
            grecaptcha.execute('6LdLk7EUAAAAAEWHuB2tabMmlxQ2-RRTLPHEGe9Y', {action: 'subscribe_newsletter'}).then(function(token) {
                $('#newsletterForm').prepend('<input type="hidden" name="token" value="' + token + '">');
                $('#newsletterForm').prepend('<input type="hidden" name="action" value="subscribe_newsletter">');
                $('#newsletterForm').unbind('submit').submit();
            });;
        });
  });
  </script>
  </body>
</html>

简单说明一下代码,在 部分中加载了 reCAPTCHA JavaScript 库。需要注意的是必须将 site key 作为render=YOUR_SITE_KEY 查询字符串参数发送加载请求。另外,还加载了 jQuery 库,以便可以使用与表单相关的实用程序方法。不过不必使用 jQuery,可以使用任何其他库来完成此步骤,甚至可以使用原生 JavaScript 来进行实现。

然后创建了一个基本表单,其中包括电子邮件文本框和“提交”按钮。最后,文件末尾有一个 JavaScript 代码段,这是实现reCAPTCHA 的关键部分。为表单创建 jQuery 提交处理程序,以便在用户提交表单时,捕获该事件并在实际提交表单之前进行必要的处理。使用 event.preventDefault() 函数来停止正常提交表单。接下来,grecaptcha 对象调用 execute 方法,该方法通过执行 AJAX 调用从 Google 服务器获取令牌。重要的是要注意,在调用 execute 方法时必须传递站点密钥和操作名称。操作名称可让管理控制台中详细了解数据。它还用于验证服务器端的 reCAPTCHA 响应结果。

当 execute 方法收到令牌响应时,它将令牌传递给 then 方法中提供的匿名函数。接下来,将两个新的隐藏变量附加到表单 token 和 action 以及它们的值。最后,通过调用 jQuery 的 submit 方法来提交表单。

处理表格提交和确认

创建一个 subscribe_newsletter_submit.php 示例后端服务

<?php
define("RECAPTCHA_V3_SECRET_KEY", 'YOUR_SECRET_HERE');
 
if (isset($_POST['email']) && $_POST['email']) {
    $email = filter_var($_POST['email'], FILTER_SANITIZE_STRING);
} else {
    // set error message and redirect back to form...
    header('location: subscribe_newsletter_form.php');
    exit;
}
 
$token = $_POST['token'];
$action = $_POST['action'];
 
// call curl to POST request
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"https://www.google.com/recaptcha/api/siteverify");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array('secret' => RECAPTCHA_V3_SECRET_KEY, 'response' => $token)));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$arrResponse = json_decode($response, true);
 
// verify the response
if($arrResponse["success"] == '1' && $arrResponse["action"] == $action && $arrResponse["score"] >= 0.5) {
    // valid submission
    // go ahead and do necessary stuff
} else {
    // spam submission
    // show error message
}

提交表单后,最重要的部分是验证与其他表单值一起提交的令牌。为此,需要在后端向 https://www.google.com/recaptcha/api/siteverify URL 发出 **POST** 请求。在上面的示例中,使用了 PHP cURL 函数来发出 POST 请求。

请求参数项分类说明
secret必传申请时的 SECRET KEY
response必传由前端站点上的 reCAPTCHA 客户端集成提供的用户响应令牌 Token
remoteip可选用户的 IP 地址
需要注意的是:必须传递密钥和令牌作为请求的参数。此外还可以增加用户的 IP 地址作为额外参数,可以提高人机识别准确率。

作为响应,将获得一个 JSON 对象,其中包含可用于验证的必要信息。如前所述,至少应该检查三件事,以确保该表格由人提交:success(状态),action(行为)和 score(得分)。

因此,通过这种方式可以在 PHP 网页中使用 Google reCAPTCHA v3 来检测并防止垃圾邮件。

其他

因为众所周知的原因,上述请求站点在中国大陆请求不通,因此可以使用官方提供的备用站点,可在大陆直连。

用法和上面的一致。


附录

参考链接

本文撰写于一年前,如出现图片失效或有任何问题,请在下方留言。博主看到后将及时修正,谢谢!
禁用 / 当前已拒绝评论,仅可查看「历史评论」。
  1. avatarImg Sky

    诺亚方舟的传说

    Quark 5.7.5.1386 iOS 15
    隐藏
  2. avatarImg Can

    写的不错,就是没看懂前端页面的部分

    QQBrowser 12.8.2 iOS 15
    隐藏
  3. avatarImg VVen

    很不错的教程,顺便问一下,有其他语言的实现方法不?

    Chrome 102.0 macOS Catalina
    隐藏