11

我在 Laravel 的网站上收到了一个联系表,我想放置一个 ReCaptcha v3,但现在我从验证中得到的结果是错误“超时或重复”。

你能帮我从头到尾吗?我不知道该去哪里...

我的头 :

<script src="https://www.google.com/recaptcha/api.js?render=My_Site_Key"></script>
  <script>
    grecaptcha.ready(function () {
      grecaptcha.execute('My_Site_Key', { action: 'contact' }).then(function (token) {
        var recaptchaResponse = document.getElementById('recaptchaResponse');
          recaptchaResponse.value = token;
      });
    });
  </script>

联系表格:

<form action="{{ route('contact.post') }}" id="contact-form" method="post" name="contactForm">
   <input type="hidden" name="_token" id="token" value="{{ csrf_token() }}">
   <input type="hidden" name="recaptcha_response" id="recaptchaResponse">
   <fieldset>
     <div class="col-sm-12">
       <input id="name" name="name" placeholder="Nom*" type="text">
     </div>
     <div class="col-sm-12">
       <input id="email" name="email" placeholder="Email*" type="text">
     </div>
     <div class="col-sm-12">
       <input id="object" name="object" placeholder="Objet*" type="text" autocomplete="off">
     </div>
     <div class="col-xs-12">
       <textarea cols="5" id="message" name="message" placeholder="Votre message...*"></textarea>
     </div>
     <div class="col-xs-12">
       <button class="submit active" id="contact-submit">ENVOYER</button>
     </div>
     <div class="error col-xs-12">
       <h3></h3>
     </div>
     <div class="success col-xs-12">
       <h3>Merci ! Votre message a été envoyé !</h3>
     </div>
   </fieldset>
</form>

路线:

Route::post('/contact', array('as' => 'contact.post', 'uses' => 'ContactController@send'));

联系控制器:

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Mail;

class ContactController extends Controller
{
    public function send() {
      $info = array(
          'name' => Input::get('name'),
          'email' => Input::get('email'),
          'object' => Input::get('object'),
          'message' => Input::get('message')
      );
      if($info['name'] == "" || $info['email'] == "" || $info['object'] == "" || $info['message'] == "") {
          return json_encode(['response' => 'Tous les champs doivent être remplis !']);
      }
      if(!filter_var($info['email'], FILTER_VALIDATE_EMAIL)) {
          return json_encode(['response' => 'Vous devez rentrer une adresse e-mail valide !']);
      }
      $ip = Request()->ip();

      // Build POST request:
      $recaptcha_url = 'https://www.google.com/recaptcha/api/siteverify';
      $recaptcha_secret = 'My_Secret_Key';
      $recaptcha_response = $_POST['recaptcha_response'];
      // Make and decode POST request:
      $recaptcha = file_get_contents($recaptcha_url . '?secret=' . $recaptcha_secret . '&response=' . $recaptcha_response);
      $recaptcha = json_decode($recaptcha);
      // Take action based on the score returned:
      if ($recaptcha->score < 0.5) {
          return json_encode(['response' => 'Vous êtes considéré comme Bot/Spammer !', 'score' => $recaptcha->score]);
      }

      Mail::send(['email.html.contact', 'email.text.contact'], ['info' => $info, 'ip' => $ip], function($message) use ($info) {
          $message->to('contact@bryangossuin.be')->subject('Bryan Gossuin | Formulaire de contact');
          $message->replyTo($info['email'], $info['name']);
      });
      return json_encode(['response' => 'success','']);
  }
}

最后的javascript

      $('#contact-form').on('submit', function(e) {
          e.preventDefault();
          swal({
              title: "Souhaitez-vous vraiment envoyer ce mail ?",
              icon: "warning",
              buttons: {
                cancel: {
                  text: "Annuler",
                  value: false,
                  visible: true,
                  closeModal: true,
                },
                confirm: "Envoyer",
              }
            })
            .then((value) => {
              if (value) {
                  $.ajax({
                          method: "POST",
                          url: "contact",
                          cache: false,
                          data: $(this).serialize(),
                          dataType: 'json',
                          success: function(json) {
                              console.log(json.score);
                              if (json.response == 'success') {
                                  $('#contact-form').trigger("reset");
                                  swal("E-mail envoyé", "Merci de votre demande !", "success");
                              } else {
                                  swal("Erreur !", json.response, "error");
                              }
                          }
                      }
                  )
               }
            });
      });

我从谷歌得到的输出是

{
  "success": false,
  "error-codes": [
    "timeout-or-duplicate"
  ]
}

我希望它是

{
  "success": true,
  "score" : x,
  "error-codes": '',
}

我想问题是因为«方法帖子»被使用了两次,因为当我直接在 API 上检查 Google 以验证用户令牌时,它显示了代码但在我刷新页面后它显示我«超时或重复»但是我不知道如何解决这个问题

4

5 回答 5

7

文档中所述,此错误是由以下原因引起的:

  1. 令牌有效期已过期(获取响应令牌后,需在两分钟内验证)
  2. 令牌以前已经使用过。要确认这一点,请在使用之前记录令牌值(错误日志、本地文件等)

我的分辨率为 1,设置一个调用 set token 函数的时间间隔,所以它每 2 分钟刷新一次。

$(document).ready(function() {

            SetCaptchaToken();
            setInterval(function () { SetCaptchaToken(); }, 2 * 60 * 1000);

    });

2的分辨率,修复你的代码:)

于 2019-11-05T15:10:28.183 回答
6

我是从人们双击表单上的提交按钮那里得到的。

于 2019-06-26T05:46:58.350 回答
4

每次页面重新加载时,您都会从 google 获得一个新令牌。您只能使用该令牌一次。不知何故,如果您多次使用该令牌从 google Api 获取响应,您将收到该错误。检查此错误参考https://developers.google.com/recaptcha/docs/verify?hl=en

于 2019-03-28T05:54:56.093 回答
3

问题是这段代码:

<script src="https://www.google.com/recaptcha/api.js?render=My_Site_Key"></script>
  <script>
    grecaptcha.ready(function () {
      grecaptcha.execute('My_Site_Key', { action: 'contact' }).then(function (token) {
        var recaptchaResponse = document.getElementById('recaptchaResponse');
          recaptchaResponse.value = token;
      });
    });
  </script>

如文档execute中所述,令牌仅在您被调用后 2 分钟内有效:

注意:reCAPTCHA 令牌在两分钟后过期。如果您使用 reCAPTCHA 保护操作,请确保在用户执行操作时调用 execute。

因此,如果您在联系表单上花费超过 2 分钟,则会收到超时错误。这就是为什么它在文档中建议仅execute在用户实际提交您的表单/采取行动时才调用。在 vanilla JS 中,它看起来像这样:

<script src="https://www.google.com/recaptcha/api.js?render=My_Site_Key"></script>
<script>
  grecaptcha.ready(function() {
      document.getElementById('contact-form').addEventListener("submit", function(event) {
        event.preventDefault();
        grecaptcha.execute('My_Site_Key', {action: 'contact'}).then(function(token) {
           document.getElementById("recaptchaResponse").value= token; 
           document.getElementById('contact-form').submit();
        });
      }, false);
  });
</script>
于 2020-02-05T13:04:59.017 回答
1

我一直在搜索与您的用例特别相似的答案。

reCaptcha V3 没有重置 API。

当您的密码或电子邮件身份验证失败时,我解决了这个问题,如果失败,请在您的 AJAX 上再次执行此操作。这样该值就可以替换为新的 g-token 而无需再次重新加载站点,因为像我一样遵循 Google 文档,脚本在您的“登录页面”准备就绪时执行

 grecaptcha.ready(function() {
              grecaptcha.execute('abhkdfhlasdfhldafhlashflasdhl', {action: 'submit'}).then(function(token) {
                document.getElementById('g-token').value = token;
              });
            });
于 2021-02-10T20:06:21.223 回答