reCaptcha v3 handle score callback

后端 未结 3 2085
天涯浪人
天涯浪人 2020-12-07 01:15

I followed recaptcha v3 example and managed to make it return a callback with a score for a page, similar with their demo.

What I don\'t understand is how to

相关标签:
3条回答
  • 2020-12-07 01:26

    If JavaScript is disabled, reCAPTCHA doesn't work anyway and most form submissions will/should fail if bot protection is critical to you.

    As for the score that V3 returns, it is entirely up to you how you handle it.

    Generally this is handled on form validations. The with V3 you could require the g-response value to be greater than 0.8 or something to your liking. Exact implementation varies greatly by how your app is structured.

    From the docs: reCAPTCHA v3 returns a score (1.0 is very likely a good interaction, 0.0 is very likely a bot). Based on the score, you can take variable action in the context of your site.

    0 讨论(0)
  • 2020-12-07 01:30

    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 App\Http\Requests;
    
    use App\Rules\RecaptchaV3;
    use Illuminate\Foundation\Http\FormRequest;
    
    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 App\Rules;
    
    use GuzzleHttp\Client;
    use Illuminate\Contracts\Validation\Rule;
    
    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.

    0 讨论(0)
  • 2020-12-07 01:40

    Unfortunately, recaptcha v3 does not have challenge methods, which means we need to handle the score threshold in our own server side.

    The best solution would be that apply both v2 and v3 together, e.g. if v3 fails threshold, then it pops up v2 challenge. The official site suggests to use 2-way authentication e.g. SMS. However, I don't think 70% of people would do it.

    I have created a composer package for Laravel framework which supports score settings. You can check the source code in github recaptcha:

    You can do score comparison for your own score handler.

    The basic usage would be like:

    {!!  GoogleReCaptchaV3::requireJs() !!} 
    <form method="POST" action="/verify">
    @csrf
    {!!  GoogleReCaptchaV3::render('contact_us') !!}
    
    <input type="submit" value="submit"> </form>
    
    0 讨论(0)
提交回复
热议问题