Is it possible to combine Google's incredible reCAPTCHA and Matias Meno's incredible dropzone.js, to prevent attacks and deter spam bots?
Asked
Active
Viewed 653 times
1 Answers
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
);
}
?>
-
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