reCAPTCHA token should be validated server side. First of all, attach generated token into your form:
grecaptcha.ready(function() {
grecaptcha.execute('{{env('RECAPTCHA_V3_PUBLIC_KEY')}}', {action: 'contactform'}).then(function(token) {
$('<input>').attr({
type: 'hidden',
name: 'g-recaptcha-response',
value: token
}).prependTo('.contact-form')
});
});
Then when you capture the input on you controller, you can use a custom form request:
<?php
namespace AppHttpRequests;
use AppRulesRecaptchaV3;
use IlluminateFoundationHttpFormRequest;
class ContactFormRequest extends FormRequest
{
public function rules()
{
$rules = [
'name' => 'required',
'email' => 'required|email',
'message' => 'required',
'g-recaptcha-response' => ['required', new RecaptchaV3],
];
return $rules;
}
...
}
g-recaptcha-response
field is required
so if users disable JS they will get an error when form input is validated.
Next for g-recaptcha-response
we apply a custom validation rule: RecaptchaV3.
Here's my implementation:
<?php
namespace AppRules;
use GuzzleHttpClient;
use IlluminateContractsValidationRule;
class RecaptchaV3 implements Rule
{
public function passes($attribute, $value)
{
$client = new Client();
$response = $client->post('https://www.google.com/recaptcha/api/siteverify', [
'form_params' => [
'secret' => env('RECAPTCHA_V3_PRIVATE_KEY'),
'response' => $value,
'remoteip' => $_SERVER['REMOTE_ADDR'],
]
]);
$decoded = json_decode($response->getBody());
return $decoded->success;
}
public function message()
{
return "You didn't pass reCAPTCHA challenge!";
}
}
Next, in your controller use the above form request:
public function processContactForm(ContactFormRequest $request)
{
...
}
Hope this helps.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…