laravel 使用 ReCaptcha v3 时出现“超时或重复”错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/55308499/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
I got "timeout-or-duplicate" error using ReCaptcha v3
提问by Saku
I got a contact form on my website on Laravel and I'd like to place a ReCaptcha v3 but for now the result I got from the verification is the error "timeout-or-duplicate".
我在 Laravel 的网站上有一个联系表格,我想放置一个 ReCaptcha v3,但现在我从验证中得到的结果是错误“超时或重复”。
Can you help me from A to Z ? I don't know where to go...
你能帮我从头到尾吗?我不知道去哪里...
My head :
我的头 :
<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>
The contact form :
联系方式:
<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:
路线:
Route::post('/contact', array('as' => 'contact.post', 'uses' => 'ContactController@send'));
The Contact Controller :
联系人控制器:
<?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('[email protected]')->subject('Bryan Gossuin | Formulaire de contact');
$message->replyTo($info['email'], $info['name']);
});
return json_encode(['response' => 'success','']);
}
}
Finaly the javascript
最后是 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");
}
}
}
)
}
});
});
The output I got from google is
我从谷歌得到的输出是
{
"success": false,
"error-codes": [
"timeout-or-duplicate"
]
}
and I expect it to be
我希望它是
{
"success": true,
"score" : x,
"error-codes": '',
}
I guess the problem is because the ??method post?? is used two times because when I Check directly On the API Google to verify the user token it show le thé code but right after I refresh the page it show me ??timeout or duplicate?? but I dont know how to fix this
我猜问题是因为 ??method post?? 使用了两次,因为当我直接在 API 上检查 Google 以验证用户令牌时,它会显示 le 代码,但在我刷新页面后,它会显示给我?超时或重复?但我不知道如何解决这个问题
回答by Nihar Sarkar
Every time the page reloads you get a new token from google . You can use that token only once . Somehow if you are using that token more than once to get the response from google Api , you will get that error . Check this error reference https://developers.google.com/recaptcha/docs/verify?hl=en
每次页面重新加载时,您都会从 google 获得一个新令牌。您只能使用该令牌一次。不知何故,如果您多次使用该令牌来获取来自 google Api 的响应,您将收到该错误。检查此错误参考https://developers.google.com/recaptcha/docs/verify?hl=en
回答by Jorge
As stated in the documentationthis error is caused by:
如文档中所述,此错误是由以下原因引起的:
- Validity time of the token expired (After you get the response token, you need to verify it within two minutes)
- Token has been used previously. To confirm that, log the token value before is used (error log, local file, whatever)
- 令牌有效期已过(收到响应令牌后,需要在两分钟内进行验证)
- 之前已经使用过令牌。要确认这一点,请在使用之前记录令牌值(错误日志、本地文件等)
My resolution for 1, set an interval that calls the set token function, so it is refreshed every 2 minutes.
我的分辨率为1,设置一个调用set token函数的间隔,所以每2分钟刷新一次。
$(document).ready(function() {
SetCaptchaToken();
setInterval(function () { SetCaptchaToken(); }, 2 * 60 * 1000);
});
Resolution for 2, fix your code :)
解决方案 2,修复您的代码 :)
回答by Matthew Lock
I got this from people double clicking the submit button on the form.
我从人们双击表单上的提交按钮那里得到了这个。
回答by Adam
The problem is this piece of code:
问题是这段代码:
<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>
The token is only valid for 2 minutes after you execute
is called as stated in the docs:
如文档中execute
所述,令牌仅在您被调用后 2 分钟内有效:
Note: reCAPTCHA tokens expire after two minutes. If you're protecting an action with reCAPTCHA, make sure to call execute when the user takes the action.
注意:reCAPTCHA 令牌在两分钟后过期。如果您使用 reCAPTCHA 保护操作,请确保在用户执行操作时调用 execute。
Thus, if you spend more then 2 minutes on the contact-form, you get the timout error,. Thats why its recommended in the docs to only call execute
if the user actually submits your form / takes action. In vanilla JS it would look like this:
因此,如果您在联系表单上花费的时间超过 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>