如何为 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.phpsubscribe_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 方法中提供的匿名函数。接下来,将两个新的隐藏变量附加到表单 tokenaction 以及它们的值。最后,通过调用 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
    IP 属地 未知
  2. avatarImg Can

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

    QQBrowser 12.8.2 iOS 15
    IP 属地 未知
  3. avatarImg VVen

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

    Chrome 102.0 macOS Catalina
    IP 属地 未知