Hi Admin and walterwick,
Ok, let’s code then.
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://challenges.cloudflare.com/turnstile/v0/siteverify');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
'secret' => SECRET_KEY,
'response' => $_POST['cf-turnstile-response'],
'remoteip' => $ip,
]));
$output = curl_exec($ch);
curl_close($ch);
$response = json_decode($output, true);
if(json_last_error() !== JSON_ERROR_NONE){
// cannot verify at this time, make sure to let user know it's not their fault
}
if(!(is_array($response) && sizeof($response) > 0)){
// verification fail, you wont't get [success] if it's not an array in the first place
}
if(sizeof(array_diff(['success','hostname','error-codes','challenge_ts'], array_keys($response))) > 0){
// verification fail, not all required fields exists
}
if( !!$response['success'] &&
$response['hostname'] === 'your host name here' &&
strtotime('now') - strtotime($response['challenge_ts']) < YOUR_ACCEPTED_DELAY){
// success
}
Welp, it gets the job done. Personally would use an OOP class to handle this but since I’m not sure how Walter’s site is developed, the above should serve as a starting reference.
I have another class that returns the IP for me so I’ll assign that to $ip
, if such a function does not exist then you can use this:
<?php
$headers = getallheaders();
$headers = array_change_key_case($headers, CASE_LOWER);
if(array_key_exists('cf-connecting-ip', $headers)){
$ip = $headers['cf-connecting-ip'];
}
In the worst-case scenario that you somehow aren’t using Cloudflare for your site and you do not have that header, here’s some old code I used back a decade ago somewhere when PHP 4 was still a thing.
Just before you copy and paste, do note that certain headers with this method are not secure anymore as headers can be spoofed, even to put local IP addresses, so only take it as a reference. I believe Cloudflare should also be able to identify this on their end if you simply pass through the IP, it will also be an indicator for them to reject the request and protect you.
<?php
$ip = '';
if (array_key_exists('HTTP_CLIENT_IP', $_SERVER)){
$ip = $_SERVER['HTTP_CLIENT_IP'];
}
else if(array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)){
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
else if(array_key_exists('HTTP_X_FORWARDED', $_SERVER)){
$ip = $_SERVER['HTTP_X_FORWARDED'];
}
else if(array_key_exists('HTTP_FORWARDED_FOR', $_SERVER)){
$ip = $_SERVER['HTTP_FORWARDED_FOR'];
}
else if(array_key_exists('HTTP_FORWARDED', $_SERVER)){
$ip = $_SERVER['HTTP_FORWARDED'];
}
else if(array_key_exists('REMOTE_ADDR', $_SERVER)){
$ip = $_SERVER['REMOTE_ADDR'];
}
if(empty($ip)){
// At this point, you might as well drop the request without even pinging CF.
}
For OOP and MVC, just place this into an appropriate class and call the function your way.
Cheers!