mirror of
https://github.com/phpbb/phpbb.git
synced 2025-08-10 18:54:08 +02:00
Merge pull request #5902 from mrgoldy/ticket/15937
[ticket/15937] Google reCAPTCHA v3 Plugin
This commit is contained in:
350
phpBB/phpbb/captcha/plugins/recaptcha_v3.php
Normal file
350
phpBB/phpbb/captcha/plugins/recaptcha_v3.php
Normal file
@@ -0,0 +1,350 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\captcha\plugins;
|
||||
|
||||
/**
|
||||
* Google reCAPTCHA v3 plugin.
|
||||
*/
|
||||
class recaptcha_v3 extends captcha_abstract
|
||||
{
|
||||
/**
|
||||
* Possible request methods to verify the token.
|
||||
*/
|
||||
const CURL = 'curl';
|
||||
const POST = 'post';
|
||||
const SOCKET = 'socket';
|
||||
|
||||
/**
|
||||
* Possible domain names to load the script and verify the token.
|
||||
*/
|
||||
const GOOGLE = 'google.com';
|
||||
const RECAPTCHA = 'recaptcha.net';
|
||||
|
||||
/** @var array CAPTCHA types mapped to their action */
|
||||
static protected $actions = [
|
||||
0 => 'default',
|
||||
CONFIRM_REG => 'register',
|
||||
CONFIRM_LOGIN => 'login',
|
||||
CONFIRM_POST => 'post',
|
||||
CONFIRM_REPORT => 'report',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get CAPTCHA types mapped to their action.
|
||||
*
|
||||
* @static
|
||||
* @return array
|
||||
*/
|
||||
static public function get_actions()
|
||||
{
|
||||
return self::$actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute.
|
||||
*
|
||||
* Not needed by this CAPTCHA plugin.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute demo.
|
||||
*
|
||||
* Not needed by this CAPTCHA plugin.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute_demo()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get generator class.
|
||||
*
|
||||
* Not needed by this CAPTCHA plugin.
|
||||
*
|
||||
* @throws \Exception
|
||||
* @return void
|
||||
*/
|
||||
public function get_generator_class()
|
||||
{
|
||||
throw new \Exception('No generator class given.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get CAPTCHA plugin name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name()
|
||||
{
|
||||
return 'CAPTCHA_RECAPTCHA_V3';
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicator that this CAPTCHA plugin requires configuration.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has_config()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize this CAPTCHA plugin.
|
||||
*
|
||||
* @param int $type The CAPTCHA type
|
||||
* @return void
|
||||
*/
|
||||
public function init($type)
|
||||
{
|
||||
/**
|
||||
* @var \phpbb\language\language $language Language object
|
||||
*/
|
||||
global $language;
|
||||
|
||||
$language->add_lang('captcha_recaptcha');
|
||||
|
||||
parent::init($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not this CAPTCHA plugin is available and setup.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_available()
|
||||
{
|
||||
/**
|
||||
* @var \phpbb\config\config $config Config object
|
||||
* @var \phpbb\language\language $language Language object
|
||||
*/
|
||||
global $config, $language;
|
||||
|
||||
$language->add_lang('captcha_recaptcha');
|
||||
|
||||
return ($config->offsetGet('recaptcha_v3_key') ?? false)
|
||||
&& ($config->offsetGet('recaptcha_v3_secret') ?? false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the ACP page for configuring this CAPTCHA plugin.
|
||||
*
|
||||
* @param string $id The ACP module identifier
|
||||
* @param \acp_captcha $module The ACP module basename
|
||||
* @return void
|
||||
*/
|
||||
public function acp_page($id, $module)
|
||||
{
|
||||
/**
|
||||
* @var \phpbb\config\config $config Config object
|
||||
* @var \phpbb\language\language $language Language object
|
||||
* @var \phpbb\log\log $phpbb_log Log object
|
||||
* @var \phpbb\request\request $request Request object
|
||||
* @var \phpbb\template\template $template Template object
|
||||
* @var \phpbb\user $user User object
|
||||
*/
|
||||
global $config, $language, $phpbb_log, $request, $template, $user;
|
||||
|
||||
$module->tpl_name = 'captcha_recaptcha_v3_acp';
|
||||
$module->page_title = 'ACP_VC_SETTINGS';
|
||||
|
||||
$form_key = 'acp_captcha';
|
||||
add_form_key($form_key);
|
||||
|
||||
if ($request->is_set_post('submit'))
|
||||
{
|
||||
if (!check_form_key($form_key))
|
||||
{
|
||||
trigger_error($language->lang('FORM_INVALID') . adm_back_link($module->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
$config->set('recaptcha_v3_key', $request->variable('recaptcha_v3_key', '', true));
|
||||
$config->set('recaptcha_v3_secret', $request->variable('recaptcha_v3_secret', '', true));
|
||||
$config->set('recaptcha_v3_domain', $request->variable('recaptcha_v3_domain', '', true));
|
||||
$config->set('recaptcha_v3_method', $request->variable('recaptcha_v3_method', '', true));
|
||||
|
||||
foreach (self::$actions as $action)
|
||||
{
|
||||
$config->set("recaptcha_v3_threshold_{$action}", $request->variable("recaptcha_v3_threshold_{$action}", 0.50));
|
||||
}
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_VISUAL');
|
||||
|
||||
trigger_error($language->lang('CONFIG_UPDATED') . adm_back_link($module->u_action));
|
||||
}
|
||||
|
||||
foreach (self::$actions as $action)
|
||||
{
|
||||
$template->assign_block_vars('thresholds', [
|
||||
'key' => "recaptcha_v3_threshold_{$action}",
|
||||
'value' => $config["recaptcha_v3_threshold_{$action}"] ?? 0.5,
|
||||
]);
|
||||
}
|
||||
|
||||
$template->assign_vars([
|
||||
'CAPTCHA_NAME' => $this->get_service_name(),
|
||||
'CAPTCHA_PREVIEW' => $this->get_demo_template($id),
|
||||
|
||||
'RECAPTCHA_V3_KEY' => $config['recaptcha_v3_key'] ?? '',
|
||||
'RECAPTCHA_V3_SECRET' => $config['recaptcha_v3_secret'] ?? '',
|
||||
|
||||
'RECAPTCHA_V3_DOMAIN' => $config['recaptcha_v3_domain'] ?? self::GOOGLE,
|
||||
'RECAPTCHA_V3_DOMAINS' => [self::GOOGLE, self::RECAPTCHA],
|
||||
|
||||
'RECAPTCHA_V3_METHOD' => $config['recaptcha_v3_method'] ?? self::POST,
|
||||
'RECAPTCHA_V3_METHODS' => [
|
||||
self::POST => ini_get('allow_url_fopen') && function_exists('file_get_contents'),
|
||||
self::CURL => extension_loaded('curl') && function_exists('curl_init'),
|
||||
self::SOCKET => function_exists('fsockopen'),
|
||||
],
|
||||
|
||||
'U_ACTION' => $module->u_action,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the ACP page for previewing this CAPTCHA plugin.
|
||||
*
|
||||
* @param string $id The module identifier
|
||||
* @return bool|string
|
||||
*/
|
||||
public function get_demo_template($id)
|
||||
{
|
||||
return $this->get_template();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the template for this CAPTCHA plugin.
|
||||
*
|
||||
* @return bool|string False if CAPTCHA is already solved, template file name otherwise
|
||||
*/
|
||||
public function get_template()
|
||||
{
|
||||
/**
|
||||
* @var \phpbb\config\config $config Config object
|
||||
* @var \phpbb\language\language $language Language object
|
||||
* @var \phpbb\template\template $template Template object
|
||||
* @var string $phpbb_root_path phpBB root path
|
||||
* @var string $phpEx php File extensions
|
||||
*/
|
||||
global $config, $language, $template, $phpbb_root_path, $phpEx;
|
||||
|
||||
if ($this->is_solved())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$contact = phpbb_get_board_contact_link($config, $phpbb_root_path, $phpEx);
|
||||
$explain = $this->type !== CONFIRM_POST ? 'CONFIRM_EXPLAIN' : 'POST_CONFIRM_EXPLAIN';
|
||||
|
||||
$domain = $config['recaptcha_v3_domain'] ?? self::GOOGLE;
|
||||
$render = $config['recaptcha_v3_key'] ?? '';
|
||||
|
||||
$template->assign_vars([
|
||||
'CONFIRM_EXPLAIN' => $language->lang($explain, '<a href="' . $contact . '">', '</a>'),
|
||||
|
||||
'RECAPTCHA_ACTION' => self::$actions[$this->type] ?? reset(self::$actions),
|
||||
'RECAPTCHA_KEY' => $config['recaptcha_v3_key'] ?? '',
|
||||
'U_RECAPTCHA_SCRIPT' => sprintf('//%1$s/recaptcha/api.js?render=%2$s', $domain, $render),
|
||||
|
||||
'S_CONFIRM_CODE' => true,
|
||||
'S_RECAPTCHA_AVAILABLE' => $this->is_available(),
|
||||
'S_TYPE' => $this->type,
|
||||
]);
|
||||
|
||||
return 'captcha_recaptcha_v3.html';
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the user's input.
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate()
|
||||
{
|
||||
if (!parent::validate())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->recaptcha_verify_token();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the token returned by Google reCAPTCHA v3.
|
||||
*
|
||||
* @return bool|string False on success, string containing the error otherwise
|
||||
*/
|
||||
protected function recaptcha_verify_token()
|
||||
{
|
||||
/**
|
||||
* @var \phpbb\config\config $config Config object
|
||||
* @var \phpbb\language\language $language Language object
|
||||
* @var \phpbb\request\request $request Request object
|
||||
* @var \phpbb\user $user User object
|
||||
*/
|
||||
global $config, $language, $request, $user;
|
||||
|
||||
$token = $request->variable('recaptcha_token', '', true);
|
||||
$action = $request->variable('recaptcha_action', '', true);
|
||||
$action = in_array($action, self::$actions) ? $action : reset(self::$actions);
|
||||
$threshold = (double) $config["recaptcha_v3_threshold_{$action}"] ?? 0.5;
|
||||
|
||||
// No token was provided, discard spam submissions
|
||||
if (empty($token))
|
||||
{
|
||||
return $language->lang('RECAPTCHA_INCORRECT');
|
||||
}
|
||||
|
||||
// Create the request method that should be used
|
||||
switch ($config['recaptcha_v3_method'] ?? '')
|
||||
{
|
||||
case self::CURL:
|
||||
$method = new \ReCaptcha\RequestMethod\CurlPost();
|
||||
break;
|
||||
|
||||
case self::SOCKET:
|
||||
$method = new \ReCaptcha\RequestMethod\SocketPost();
|
||||
break;
|
||||
|
||||
case self::POST:
|
||||
default:
|
||||
$method = new \ReCaptcha\RequestMethod\Post();
|
||||
break;
|
||||
}
|
||||
|
||||
// Create the recaptcha instance
|
||||
$recaptcha = new \ReCaptcha\ReCaptcha($config['recaptcha_v3_secret'], $method);
|
||||
|
||||
// Set the expected action and threshold, and verify the token
|
||||
$result = $recaptcha->setExpectedAction($action)
|
||||
->setScoreThreshold($threshold)
|
||||
->verify($token, $user->ip);
|
||||
|
||||
if ($result->isSuccess())
|
||||
{
|
||||
$this->solved = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return $language->lang('RECAPTCHA_INCORRECT');
|
||||
}
|
||||
}
|
46
phpBB/phpbb/db/migration/data/v330/google_recaptcha_v3.php
Normal file
46
phpBB/phpbb/db/migration/data/v330/google_recaptcha_v3.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\db\migration\data\v330;
|
||||
|
||||
class google_recaptcha_v3 extends \phpbb\db\migration\migration
|
||||
{
|
||||
public function effectively_installed()
|
||||
{
|
||||
return $this->config->offsetExists('recaptcha_v3_key');
|
||||
}
|
||||
|
||||
public static function depends_on()
|
||||
{
|
||||
return [
|
||||
'\phpbb\db\migration\data\v330\v330',
|
||||
];
|
||||
}
|
||||
|
||||
public function update_data()
|
||||
{
|
||||
$data = [
|
||||
['config.add', ['recaptcha_v3_key', '']],
|
||||
['config.add', ['recaptcha_v3_secret', '']],
|
||||
['config.add', ['recaptcha_v3_domain', \phpbb\captcha\plugins\recaptcha_v3::GOOGLE]],
|
||||
['config.add', ['recaptcha_v3_method', \phpbb\captcha\plugins\recaptcha_v3::POST]],
|
||||
];
|
||||
|
||||
foreach (\phpbb\captcha\plugins\recaptcha_v3::get_actions() as $action)
|
||||
{
|
||||
$data[] = ['config.add', ["recaptcha_v3_threshold_{$action}", 0.5]];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user