3

reCAPTCHA

Is it possible to combine Google's incredible reCAPTCHA and Matias Meno's incredible dropzone.js, to prevent attacks and deter spam bots?

JBithell
  • 627
  • 2
  • 11
  • 27

1 Answers1

0

Using wordpress. This is what I came up with following a few tutorials:

  • SO answer
  • codeforgeek
  • And some others I dont remember

    // Dropzone.autoDiscover = false; //I use Autodiscover
    Dropzone.options.myAwesomeDropzone = { // The camelized version of the ID of the form element
    
    // The configuration we've talked about above
    autoProcessQueue: false,
    uploadMultiple: true,
    parallelUploads: 100,
    maxFiles: 100,
    previewsContainer: '.fileupload',
    
    // The setting up of the dropzone
    init: function() {
        var myDropzone = this;
    
        // First change the button to actually tell Dropzone to process the queue.
        this.element.querySelector("input[type=submit]").addEventListener("click", function(e) {
            // Make sure that the form isn't actually being sent.
            e.preventDefault();
            e.stopPropagation();
            // myDropzone.processQueue();
    
            var valid = true;
            $('[data-required]').each(function(i,ele){
                if(ele.value == ''){
                    $(this).parent().parent().addClass('alert');
                    valid = false;
                }
            });
            if (!valid){
                e.preventDefault();
                scrollTop();
                return false;
            }
    
            // Get the recaptcha input
            var cap_input = grecaptcha.getResponse();
            $.ajax({
                url: homeUrl+'/wp-admin/admin-ajax.php',
                type: "POST",
                dataType: "JSON",
                data: {
                    "action": "verifyReCaptcha",
                    "g-recaptcha-response": cap_input
                },
                success: function(response){
                    console.log(response);
    
                    if(response == 'Good captcha'){
    
    
                        if (myDropzone.getQueuedFiles().length > 0) {
                            myDropzone.processQueue();
                        }
                        else {
                            // Upload anyway without files
                            if (wantToUpload == 'unknown') {
                                $('#noFiles').modal();
                                e.preventDefault();
                                return false;
                            }
                            else if (wantToUpload == false) {
                                myDropzone.uploadFiles([ ]);
                            }
                            else {
                                myDropzone.uploadFiles([ ]);
                            }
                        }
                    }
                    else{
                        console.log('Spammer go away');
                        $('.g-recaptcha').addClass('alert');
                    }
                }
            });
        });
    
        // Listen to the sendingmultiple event. In this case, it's the sendingmultiple event instead
        // of the sending event because uploadMultiple is set to true.
        this.on("sendingmultiple", function() {
        // Gets triggered when the form is actually being sent.
        // Hide the success button or the complete form.
        console.log('sending');
    });
        this.on("successmultiple", function(files, response) {
        // Gets triggered when the files have successfully been sent.
        // Redirect user or notify of success.
        console.log('success');
    });
        this.on("errormultiple", function(files, response) {
        // Gets triggered when there was an error sending the files.
        // Maybe show form again, and notify user of error
        console.log('error');
    });
    }
    }
    

And some html/php

<form name="" action="<?=get_permalink();?>" method="post" id="my-awesome-dropzone" class="dropzone" enctype="multipart/form-data">
    <label class="label" for="text-435">
        <?=__('Name*','gt_domain');?>
    </label>
    <input type="text" name="client-name" value="" size="40" class="input__field--manami" id="text-435" data-required="true">

    <!-- Lots of input fields -->

    <div class="col-md-8 col-xs-12 fileupload dropzone-previews dz-message">
        <h2 class="text-center" id="fileuploadtext">
            <?=__('Click or drag and drop your file here <br>(Max 60mb)','gt_domain');?>
        </h2>
    </div>
    <div class="g-recaptcha" data-sitekey="MY_PUBLIC_KEY"></div>
    <input class="dangerzone-submit" type="submit" value="<?=__('Request quote','gt_domain');?>" name="dangerzone-submit">
</form>

And for ajax validation before submitting the form:

function verifyReCaptcha(){
        $email;
        $comment;
        $captcha = false;
        if(isset($_POST['g-recaptcha-response'])){
          $captcha=$_POST['g-recaptcha-response'];
        }
        if(!$captcha){
          echo json_encode('Please check the the captcha form.');
          exit;
        }
        $response=json_decode(file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=MY_SUPER_SECRET_GOOGLE_RECAPTCHA_KEY&response=".$captcha."&remoteip=".$_SERVER['REMOTE_ADDR']), true);
        if($response['success'] == false){
          echo json_encode('You are spammer ! Get the @$%K out');
        }
        else{
          echo json_encode('Good captcha');
        }
        exit;
}
add_action( 'wp_ajax_nopriv_verifyReCaptcha', 'verifyReCaptcha' );
add_action( 'wp_ajax_verifyReCaptcha', 'verifyReCaptcha' );

And finnaly recieve form inputs and images:

<?php
if (isset($_POST['dangerzone-submit'])) {
    // print_r($_POST);
    $client = $_POST['client-name'];
    $email = $_POST['email'];
    $company = $_POST['company'];
    $phone = $_POST['phone'];
    $comments = $_POST['comments'];



    if ($_FILES) {
        foreach ($_FILES as $file => $array) {
            // print_r($array);
            if ($_FILES[$file]['error'] !== UPLOAD_ERR_OK &&  $_FILES[$file]['error'][0] !== 0) {
                echo "upload error : \n";
                print_r($_FILES[$file]['error']);
                print_r($_FILES);
                die();
            }
            $uploads_dir = ABSPATH . 'wp-content/uploads/dropzone/';
            $external_link = get_home_url().'/wp-content/uploads/dropzone/';

            foreach ($array['name'] as $key => $val) {
                print_r($key);
                $name = $array['name'][$key];
                $tmp_name = $array['tmp_name'][$key];
                $newfilename = wp_unique_filename( $uploads_dir, $name );

                $movefile = move_uploaded_file($tmp_name, $uploads_dir.$newfilename);
                $uploaded_files[] = $external_link.$newfilename;
            }
        }
    }


    sendMail( //My func for sending mail
            $client,
            $email,
            $company,
            $phone,
            $comments,
            $uploaded_files
        );

}
?>
Community
  • 1
  • 1
Jorgeuos
  • 541
  • 6
  • 28
  • Client side "verifyReCaptcha" is a very bad pattern, the only way to secure api call is a backend/server side validation of token from Google. Anyone can call your endpoint by bypassing validation. – anisite Mar 29 '21 at 17:18
  • Oh, just saw this. An old answer, and I don't remember what I was doing back then, but I'm pretty sure the validation is done in the backend, in my answer at least. – Jorgeuos Mar 17 '22 at 03:02
  • When I look at it now, it kinda looks like Typescript, but it's definitely php. – Jorgeuos Mar 17 '22 at 03:03
  • Sorry it's my bad, you are right, PHP it's not client side, I don't understand my own comment... – anisite Mar 18 '22 at 13:54