Merge pull request #763 from KuJoe/master

Added Cloudflare Turnstile as alternative to Google reCAPTCHA by @KuJoe
This commit is contained in:
Dan 2024-05-21 08:45:24 +07:00 committed by GitHub
commit 9d57e7849a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 74 additions and 27 deletions

View file

@ -59,12 +59,13 @@ google.analytics.id = ""
; Google gtag analytics
google.gtag.id = ""
; Google reCaptcha
; https://www.google.com/recaptcha/admin. Options "false" and "true"
; Login protection system Choose "google", "cloudflare", or "disable".
; https://www.google.com/recaptcha/admin
; https://developers.cloudflare.com/turnstile/
google.reCaptcha = "false"
google.reCaptcha.public = ""
google.reCaptcha.private = ""
login.protect.system = "disable"
login.protect.public = ""
login.protect.private = ""
; Pagination, RSS, and JSON
posts.perpage = "10"

View file

@ -37,7 +37,7 @@ cache_off = "Cache off"
cache_timestamp = "Cache timestamp"
cancel = "Cancel"
cannot_read_feed_content = "Cannot read feed content"
captcha_error = "reCaptcha not correct"
captcha_error = "Captcha failed"
categories = "Categories"
category = "Category"
check_update = "Check for update"
@ -87,7 +87,7 @@ front_page_displays = "Front page displays"
full_post = "Full post"
general = "General"
general_settings = "General Settings"
get_one_here = "Get one here"
get_one_here = "Obtain your reCaptcha keys here: "
github_pre_release = "Github pre-release"
google_analytics = "Google Analytics"
google_analytics_legacy = "Google Analytics (legacy)"
@ -186,7 +186,7 @@ reading = "Reading"
writing = "Writing"
reading_settings = "Reading Settings"
writing_settings = "Writing Settings"
recaptcha = "reCAPTCHA"
recaptcha = "Login Protection"
recent_posts = "Recent posts"
recent_posts_widget_at_most = "Recent posts widget at most"
regular_post = "Regular post"
@ -297,3 +297,5 @@ mfa_error = "MFA code is not correct"
disablemfa = "Disable MFA"
enable_auto_save = "Enable Auto Save to Drafts"
explain_autosave = "When enabled, new posts or pages will automatically be saved as a draft every 60 seconds after you start writing."
login_protect_system = "Login protection system"
cloudflare_info = "Review Cloudflare's Turnstile documentation: "

View file

@ -176,35 +176,42 @@
<h4><?php echo i18n('Recaptcha');?></h4>
<hr>
<p><?php echo i18n('Get_one_here');?> <a target="_blank" href="https://www.google.com/recaptcha/admin">https://www.google.com/recaptcha/admin</a>
<p><?php echo i18n('Cloudflare_info');?> <a target="_blank" href="https://developers.cloudflare.com/turnstile/">https://developers.cloudflare.com/turnstile/</a>
<div class="form-group row">
<label class="col-sm-2 col-form-label"><?php echo i18n('Recaptcha');?></label>
<div class="col-sm-10">
<div class="col-sm-10">
<div class="form-check">
<input class="form-check-input" type="radio" name="-config-google.reCaptcha" id="google.reCaptcha1" value="true" <?php if (config('google.reCaptcha') === 'true'):?>checked<?php endif;?>>
<label class="form-check-label" for="google.reCaptcha1">
<?php echo i18n('Enable');?>
<input class="form-check-input" type="radio" name="-config-login.protect.system" id="login.protect.system1" value="disable" <?php if (config('login.protect.system') === 'disable'):?>checked<?php endif;?>>
<label class="form-check-label" for="login.protect.system1">
<?php echo i18n('Disabled');?>
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="-config-google.reCaptcha" id="google.reCaptcha2" value="false" <?php if (config('google.reCaptcha') === 'false'):?>checked<?php endif;?>>
<label class="form-check-label" for="google.reCaptcha2">
<?php echo i18n('Disable');?>
<input class="form-check-input" type="radio" name="-config-login.protect.system" id="login.protect.system2" value="google" <?php if (config('login.protect.system') === 'google'):?>checked<?php endif;?>>
<label class="form-check-label" for="login.protect.system2">
Google reCaptcha
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="-config-login.protect.system" id="login.protect.system3" value="cloudflare" <?php if (config('login.protect.system') === 'cloudflare'):?>checked<?php endif;?>>
<label class="form-check-label" for="login.protect.system3">
Cloudflare Turnstile
</label>
</div>
</div>
</div>
</div>
<div class="form-group row">
<label for="google.reCaptcha.public" class="col-sm-2 col-form-label"><?php echo i18n('Site_Key');?></label>
<label for="login.protect.public" class="col-sm-2 col-form-label"><?php echo i18n('Site_Key');?></label>
<div class="col-sm-10">
<input type="text" name="-config-google.reCaptcha.public" class="form-control" id="google.reCaptcha.public" value="<?php echo valueMaker(config('google.reCaptcha.public'));?>" placeholder="<?php echo i18n('widget_key_placeholder');?>">
<input type="text" name="-config-login.protect.public" class="form-control" id="login.protect.public" value="<?php echo valueMaker(config('login.protect.public'));?>" placeholder="<?php echo i18n('widget_key_placeholder');?>">
</div>
</div>
<div class="form-group row">
<label for="google.reCaptcha.private" class="col-sm-2 col-form-label"><?php echo i18n('Secret_Key');?></label>
<label for="login.protect.private" class="col-sm-2 col-form-label"><?php echo i18n('Secret_Key');?></label>
<div class="col-sm-10">
<input type="text" name="-config-google.reCaptcha.private" class="form-control" id="google.reCaptcha.private" value="<?php echo valueMaker(config('google.reCaptcha.private'));?>" placeholder="<?php echo i18n('widget_key_placeholder');?>">
<input type="text" name="-config-login.protect.private" class="form-control" id="login.protect.private" value="<?php echo valueMaker(config('login.protect.private'));?>" placeholder="<?php echo i18n('widget_key_placeholder');?>">
</div>
</div>
<br>

View file

@ -24,9 +24,14 @@
<label><?php echo i18n('MFACode');?></label>
<input type="text" class="form-control" name="mfacode" placeholder="<?php echo i18n('verify_code'); ?>"/>
<br>
<?php if (config('google.reCaptcha') === 'true'): ?>
<?php if (config('login.protect.system') === 'google'): ?>
<script src='https://www.google.com/recaptcha/api.js'></script>
<div class="g-recaptcha" data-sitekey="<?php echo config("google.reCaptcha.public"); ?>"></div>
<div class="g-recaptcha" data-sitekey="<?php echo config("login.protect.public"); ?>"></div>
<br/>
<?php endif; ?>
<?php if (config('login.protect.system') === 'cloudflare'): ?>
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" defer></script>
<div style="text-align:center;" class="cf-turnstile" data-sitekey="<?php echo config("login.protect.public"); ?>"></div>
<br/>
<?php endif; ?>
<input type="submit" class="btn btn-primary" name="submit" value="<?php echo i18n('Login');?>"/>

View file

@ -27,9 +27,9 @@
"google.wmt.id",
"google.analytics.id",
"google.gtag.id",
"google.reCaptcha",
"google.reCaptcha.public",
"google.reCaptcha.private",
"login.protect.system",
"login.protect.public",
"login.protect.private",
"posts.perpage",
"category.perpage",
"tag.perpage",

View file

@ -121,7 +121,13 @@ get('/index', function () {
post('/login', function () {
$proper = (is_csrf_proper(from($_REQUEST, 'csrf_token')));
if (config('login.protect.system') === 'google') {
$captcha = isCaptcha(from($_REQUEST, 'g-recaptcha-response'));
} elseif (config('login.protect.system') === 'cloudflare') {
$captcha = isTurnstile(from($_REQUEST, 'cf-turnstile-response'));
} else {
$captcha = true;
}
$user = from($_REQUEST, 'user');
$pass = from($_REQUEST, 'password');

View file

@ -3561,12 +3561,9 @@ function remove_html_comments($content)
// Google recaptcha
function isCaptcha($reCaptchaResponse)
{
if (config('google.reCaptcha') != 'true') {
return true;
}
$url = "https://www.google.com/recaptcha/api/siteverify";
$options = array(
"secret" => config("google.reCaptcha.private"),
"secret" => config("login.protect.private"),
"response" => $reCaptchaResponse,
"remoteip" => $_SERVER['REMOTE_ADDR'],
);
@ -3581,6 +3578,35 @@ function isCaptcha($reCaptchaResponse)
return ($json['success']);
}
// Cloudflare Turnstile
function isTurnstile($turnstileResponse)
{
$public = config("login.protect.public");
$private = config("login.protect.private");
$ip = $_SERVER['REMOTE_ADDR'];
$url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';
$data = array('secret' => $private, 'response' => $turnstileResponse, 'remoteip' => $ip);
$options = array(
'http' => array(
'method' => 'POST',
'content' => http_build_query($data))
);
$stream = stream_context_create($options);
$fileContent = file_get_contents($url, false, $stream);
if ($fileContent === false) {
return false;
}
$json = json_decode($fileContent, true);
if ($json == false) {
return false;
}
return ($json['success']);
}
// Get video ID
function get_video_id($url)
{