使用谷歌的新不可见reCaptcha进行实现

36

我正在建设一个PHP网站,在登录表单中我想加入验证码。我选择了Google的新Invisible reCaptcha,但我在实施方面遇到了问题(HTML部分,PHP正常工作)。

我现在用于“普通”reCaptcha的代码如下(根据Google reCaptcha说明以及此代码已经起作用):

<form action=test.php method="POST">
   <input type="text" name="email" placeholder="Email">
   <input type="password" name="password" placeholder="Password">

   <!-- <Google reCaptcha> -->
   <div class="g-recaptcha" data-sitekey="<sitekey>"></div>
   <!-- </Google reCaptcha> -->

   <input type="submit" name="login" class="loginmodal-submit" value="Login">
</form>

当我注册并等待了大约24小时后收到确认电子邮件,其中包含了一些说明,内容如下:

Invisible reCAPTCHA 集成

  1. 如果您还没有将您的网站与 reCAPTCHA v2 集成,请按照我们的开发者指南进行实现。

  2. 请确保已经将您的网站密钥添加到 Invisible reCAPTCHA 的白名单中。

  3. 为启用 Invisible reCAPTCHA,您可以直接将参数添加到 HTML 按钮中,而不是将其放在 div 中。

    3a. data-callback =“” 。这个和 checkbox captcha 差不多,但对于 invisible 是必需的。

    3b. data-badge:这允许您重新定位 reCAPTCHA 徽章(即徽标和“受reCAPTCHA保护”文本)。有效选项包括“bottomright”(默认值)、“bottomleft”或“inline”,可将徽章直接放置在按钮上方。如果使徽章处于 inline 状态,则可以直接控制徽章的 CSS。

  4. 验证用户的响应没有变化。

我的问题是HTML实现(因此我需要关于步骤3的帮助。步骤1,2和4对我有效。)根据说明,其余部分我已经使用普通reCaptcha实现了。我不理解 data-callback 和 data-badge 是什么以及它们是如何工作的。如果有一个与我的表单设置相对应的实现隐藏式reCaptcha的代码示例,那就太棒了!


你需要“PHP”标签吗?被接受的答案是JavaScript通用的,而不是仅适用于PHP。 - Michael Freidgeim
@MichaelFreidgeim 没错。我已经将 PHP 标签更改为 JavaScript 标签。 - L.Johnson
5个回答

41

隐形 reCAPTCHA

实现 Google 的新隐形 reCAPTCHA 与我们添加 v2 到网站的方式非常相似。您可以像平常一样将其添加为自己的容器,或者使用将其添加到表单提交按钮的新方法。希望本指南能够帮助您走上正确的道路。

独立的验证码容器

实现 reCAPTCHA 需要几个步骤:

- Sitekey
- Class
- Callback
- Bind

这将是你最终的目标。

<div class="g-recaptcha" data-sitekey="<sitekey>" 
   data-bind="recaptcha-submit" data-callback="submitForm"> 
</div>
在使用独立的方法时,您必须将 data-bind 设置为提交按钮的 ID。如果未设置此项,您的验证码将不会是不可见的。
还必须使用回调来提交表单。不可见的验证码将取消提交按钮的所有事件,因此您需要回调来实际传递提交。
<script>
function submitForm() {
    var form = document.getElementById("ContactForm");
    if (validate_form(form)) {
        form.submit();
    } else {
        grecaptcha.reset();
    }
}
</script>

请注意示例回调函数中还有自定义表单验证。非常重要的一点是,当验证失败时,您必须重置reCAPTCHA,否则您将无法重新提交表单,直到验证码过期。

隐形验证码按钮

很多内容与上面独立的验证码相同,但不同的是,所有内容都放在提交按钮上。

这将是您的目标。

<button class="g-recaptcha" data-sitekey="<sitekey>" 
   data-callback="submitForm" data-badge="inline" type="submit">
  Submit</button>

这里有些新内容,data-badge。这是一个被插入到DOM中的div,其中包含reCAPTCHA所需的输入。它有三个可能的值:bottomleft,bottomright,inline。Inline会使其直接显示在提交按钮上方,并允许您控制其样式。

回答您的问题

<form action="test.php" method="POST" id="theForm">
    <script>
    function submitForm() {
        document.getElementById("theForm").submit();
    }
    </script>
    <input type="text" name="email" placeholder="Email">
    <input type="password" name="password" placeholder="Password">

    <div class="g-recaptcha" data-sitekey="<sitekey>" data-bind="recaptcha-submit" data-callback="submitForm"></div>

    <input type="submit" name="login" class="loginmodal-submit" id="recaptcha-submit" value="Login">
</form>

或者

<form action="test.php" method="POST" id="theForm">
    <script>
    function submitForm() {
        document.getElementById("theForm").submit();
    }
    </script>
    <input type="text" name="email" placeholder="Email">
    <input type="password" name="password" placeholder="Password">

    <button class="loginmodal-submit g-recaptcha" data-sitekey="<sitekey>" data-callback="submitForm" data-badge="inline" type="submit" value="Login">Submit</button>
</form>

我希望这可以帮助你和未来的编码人员。随着技术的发展,我会保持更新。


这对我来说还没有完全工作(我尝试了第一个例子)。它似乎正在加载,但当我按提交按钮时,我必须完成验证码(不确定这是否是错误,还是Google怀疑我是机器人 - 因为它应该是隐形的,对吧?)当我完成它时,recaptcha对话框(用于按与问题相对应的图片)消失了,如果我再次尝试点击提交按钮,则什么也不会发生。我已经在Firefox和Chrome的新安装上尝试过了。FYI,test.php文件是运行此代码的相同文件。它调用自己。 - L.Johnson
另外,如果我可以问一下。同一div中的data-callback="onSubmit"是什么意思?onSubmit实际上是什么意思?谢谢。 - L.Johnson
2
非常好!谢谢。 - L.Johnson
我该如何理解它是否对我起作用。我提交表单,但没有为我的表单提供挑战? - hakkikonu
@Allen 你好,Allen, - Jonca33
显示剩余6条评论

26

以下是如何实现客户端和服务器端(PHP)不可见reCaptcha功能的步骤:

  • 客户端
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>reCaptcha</title>

    <!--api link-->
    <script src="https://www.google.com/recaptcha/api.js" async defer></script>
    <!--call back function-->
    <script>
        function onSubmit(token) {
            document.getElementById('reCaptchaForm').submit();
        }
    </script>
</head>
<body>
<div class="container">
    <form id="reCaptchaForm" action="signup.php" method="POST">
        <input type="text" placeholder="type anything">
        <!--Invisible reCaptcha configuration-->
        <button class="g-recaptcha" data-sitekey="<your site key>" data-callback='onSubmit'>Submit</button>
        <br/>
    </form>
</div>
</body>
</html>
  • 服务器端验证:创建一个名为signup.php的文件
<?php
//only run when form is submitted
if(isset($_POST['g-recaptcha-response'])) {
    $secretKey = '<your secret key>';
    $response = $_POST['g-recaptcha-response'];     
    $remoteIp = $_SERVER['REMOTE_ADDR'];


    $reCaptchaValidationUrl = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=$secretKey&response=$response&remoteip=$remoteIp");
    $result = json_decode($reCaptchaValidationUrl, TRUE);

    //get response along side with all results
    print_r($result);

    if($result['success'] == 1) {
        //True - What happens when user is verified
        $userMessage = '<div>Success: you\'ve made it :)</div>';
    } else {
        //False - What happens when user is not verified
        $userMessage = '<div>Fail: please try again :(</div>';
    }
}
?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>reCAPTCHA Response</title>
    </head>
    <body>
        <?php
            if(!empty($userMessage)) {
                echo $userMessage;
            }
        ?>
    </body>
</html>

谷歌有关验证的文档指出,调用应该是POST方式。看起来你的代码执行的是GET方式。是否最好像这个例子中的PHP一样实现一个POST呢?(链接为:https://dev59.com/rm035IYBdhLWcg3wErrM) - FreshSnow

25

如果您正在寻找一种完全可定制的通用解决方案,甚至可以在同一页上使用多个表单,我将使用render=explicitonload=aFunctionCallback参数明确渲染reCaptcha小部件。

这是一个简单的示例:

<!DOCTYPE html>
<html>
<body>

<form action="" method="post">
    <input type="text" name="first-name-1"> <br />
    <input type="text" name="last-name-1"> <br />

    <div class="recaptcha-holder"></div>

    <input type="submit" value="Submit">
</form>

<br /><br />

<form action="" method="post">
    <input type="text" name="first-name-2"> <br />
    <input type="text" name="last-name-2"> <br />

    <div class="recaptcha-holder"></div>

    <input type="submit" value="Submit">
</form>

<script type="text/javascript">

  var renderGoogleInvisibleRecaptcha = function() {
    for (var i = 0; i < document.forms.length; ++i) {
      var form = document.forms[i];
      var holder = form.querySelector('.recaptcha-holder');
      if (null === holder){
        continue;
      }

      (function(frm){

        var holderId = grecaptcha.render(holder,{
          'sitekey': 'CHANGE_ME_WITH_YOUR_SITE_KEY',
          'size': 'invisible',
          'badge' : 'bottomright', // possible values: bottomright, bottomleft, inline
          'callback' : function (recaptchaToken) {
            HTMLFormElement.prototype.submit.call(frm);
          }
        });

        frm.onsubmit = function (evt){
          evt.preventDefault();
          grecaptcha.execute(holderId);
        };

      })(form);
    }
  };


</script>

<script src="https://www.google.com/recaptcha/api.js?onload=renderGoogleInvisibleRecaptcha&render=explicit" async defer></script>

</body>
</html>

如您所见,我正在向表单中添加一个空的

元素。为了识别应该使用reCaptcha进行保护的表单,我将在此元素上添加一个类名。在我们的示例中,我使用“recaptcha-holder”类名。

回调函数会遍历所有现有的表单,并且如果它发现我们注入的带有“recaptcha-holder”类名的元素,它就会渲染reCaptcha部件。

我一直在我的 WordPress 隐形reCaptcha插件中使用这个解决方案。如果有人想看看它是如何工作的,该插件可以在WordPress目录中下载:

https://wordpress.org/plugins/invisible-recaptcha/

希望这可以帮助到您!


谢谢,我会尽快查看。我的注册页面实际上有一个问题,里面同时包含登录表单(在菜单中)和注册表单。希望这可能解决那个问题! - L.Johnson
谢谢,它的工作方式正是我想要的,我能够在一个页面上有两个验证码。 - L.Johnson
与Google的文档不同,这是一个有帮助的起点。然而,我建议未来任何人发现此问题时采用一个建议的更改:使用frm.addEventListener('submit', function(evt) { ... });代替frm.onsubmit。我在我的FlexForms reCAPTCHA模块(https://github.com/cubiclesoft/php-flexforms-modules)中采用了类似但更灵活的方法。 - CubicleSoft
7
等一下,服务器端在哪里? - GDY
谢谢您提供的示例。我已经在我的测试网站上实现了它,它可以工作,但每次我点击提交时都会要求挑战。这在您的WordPress插件中不会发生。那么HTML示例有什么问题呢? - KAGG Design

0

这里是一个可运行的示例:

<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>ReCAPTCHA Example</title>
</head>
<body>
<div class="container">

  <form method="post" action="/contact/" id="contact-form">
    <h3 class="title-divider">
      <span>Contact Us</span>
    </h3>
    <input type="text" name="name">
    <div class="captcha"><!-- BEGIN: ReCAPTCHA implementation example. -->
      <div id="recaptcha-demo" class="g-recaptcha" data-sitekey="YOUR_RECAPTCHA_SITE_KEY" data-callback="onSuccess" data-bind="form-submit"></div>
      <script>
          var onSuccess = function (response) {
              var errorDivs = document.getElementsByClassName("recaptcha-error");
              if (errorDivs.length) {
                  errorDivs[0].className = "";
              }
              var errorMsgs = document.getElementsByClassName("recaptcha-error-message");
              if (errorMsgs.length) {
                  errorMsgs[0].parentNode.removeChild(errorMsgs[0]);
              }
              document.getElementById("contact-form").submit();
          };</script><!-- END: ReCAPTCHA implementation example. -->
    </div>
    <button id="form-submit" type="submit">Submit</button>
  </form>
  <script src="https://www.google.com/recaptcha/api.js" async defer></script>
</div>
</body>
</html>

别忘了把 YOUR_RECAPTCHA_SITE_KEY 改成你的 Google ReCAPTCHA 网站密钥。

下一步是实际验证数据。 通过向端点 https://www.google.com/recaptcha/api/siteverify 发送 POST 请求来完成此操作,其中包含您的 Secret key 和来自 reCAPTCHA 的数据,该数据由 g-recaptcha-response 标识。 根据您的 CMS/Framework,可能有许多不同的方法可以完成此操作。

您可能已经注意到屏幕右下角的 reCaptcha 徽章。 这是为了让用户知道表单现在受到 reCaptcha 的保护,因为已删除验证复选框。 但是,可以通过将其配置为内联,然后使用 CSS 修改来隐藏此徽章。

<style>
    .grecaptcha-badge {display: none;}
</style>

请注意,由于Google收集用户信息以启用reCaptcha功能,他们的服务条款要求您向用户提醒其使用。如果您隐藏徽章,则可以在页面的某个位置添加信息段落。

-6

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接