Hcaptcha.php
См. документацию.
1 <?php
2 
3 
4 /**
5  * @file
6  * @brief работа с hcaptcha
7  *
8  * каптчей защищены формы авторизизации, регистрации, восстановления пароля. Если количество попыток(взаимодействий с формами) не превышает лимитов ATTEMPTS_NUM
9  * допустимых за период ATTEMPTS_TIME секунд, то допустимо взаимодействие без капчи, в целях удобства пользователей.
10  */
11 
12 
13 namespace Wrong\Auth;
14 
15 use Wrong\Start\Env;
16 
17 /**
18  * @brief Hcaptcha класс отвечает за работу с hcaptcha
19  *
20  */
21 class Hcaptcha
22 {
23  /** путь к временному файлу */
24  const ATTEMPTS_FILE = __DIR__ . '/../../../temp/hcaptcha-attempts.json';
25 
26  /** Время в секундах, для подсчета попыток */
27  const ATTEMPTS_TIME = 3600;
28 
29  /** Количество попыток, которое может сделать пользователь, прежде чем ему потребуется решить капчу. */
30  const ATTEMPTS_NUM = 5;
31 
32  /**
33  * отправляет запрос POST в API hCaptcha с секретным ключом и токеном ответа и возвращает true, если ответ действителен.
34  *
35  * @param string $response Токен ответа, предоставленный hCaptcha
36  *
37  * @return bool Логическое значение.
38  */
39  public static function get($response)
40  {
41  $curl = curl_init();
42  curl_setopt_array($curl, array(
43  CURLOPT_URL => 'https://hcaptcha.com/siteverify',
44  CURLOPT_HEADER => false,
45  CURLOPT_RETURNTRANSFER => true,
46  CURLOPT_ENCODING => '',
47  CURLOPT_MAXREDIRS => 10,
48  CURLOPT_TIMEOUT => 0,
49  CURLOPT_FOLLOWLOCATION => true,
50  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
51  CURLOPT_SSL_VERIFYPEER => false,
52  CURLOPT_CUSTOMREQUEST => 'POST',
53  CURLOPT_POSTFIELDS => 'secret=' . Env::$e->HCAPTCHA_SECRET . '&response=' . $response,
54  CURLOPT_HTTPHEADER => array(
55  'Content-Type: application/x-www-form-urlencoded'
56  ),
57  ));
58  $result = curl_exec($curl);
59  curl_close($curl);
60  if ($result && json_decode($result)->success === true) {
61  return true;
62  }
63  return false;
64  }
65 
66  /**
67  * проверяет, разрешен ли IP-адресу доступ к сайту без ввода каптчи.
68  *
69  * @return int Количество оставшихся попыток.
70  */
71  public static function check()
72  {
73  if ($_SERVER['REMOTE_ADDR'] == '127.0.0.1') { // для локалки проверка всегда валидна
74  return self::ATTEMPTS_NUM;
75  }
76  if (!Env::$e->HCAPTCHA_SECRET) { // если не указан ключ проверка валидна всегда
77  return self::ATTEMPTS_NUM;
78  }
79  try {
80  file_exists(dirname(self::ATTEMPTS_FILE)) or mkdir(dirname(self::ATTEMPTS_FILE), 0755);
81  if (!file_exists(dirname(self::ATTEMPTS_FILE))) {
82  throw new \Error('Path does not create');
83  }
84  } catch (\Throwable $th) {
85  exit($th);
86  }
87  $file = new \SplFileObject(self::ATTEMPTS_FILE, 'a+b');
88  $file->flock(LOCK_EX);
89  $file->rewind();
90  $data = $file->fread($file->getSize());
91  $data = empty($data) ? [] : json_decode($data, true);
92  $data = array_filter($data, function ($time) {
93  if ($time + self::ATTEMPTS_TIME < time()) {
94  return false;
95  }
96  return true;
97  }, ARRAY_FILTER_USE_KEY);
98  $file->ftruncate(0);
99  $file->fwrite(json_encode($data));
100  $file->flock(LOCK_UN);
101  return self::ATTEMPTS_NUM - count(array_keys($data, $_SERVER['REMOTE_ADDR'])) > 0;
102  }
103 
104  /**
105  * записывает очередное взаимодействие(попытку)
106  */
107  public static function attempt()
108  {
109  try {
110  file_exists(dirname(self::ATTEMPTS_FILE)) or mkdir(dirname(self::ATTEMPTS_FILE), 0755);
111  if (!file_exists(dirname(self::ATTEMPTS_FILE))) {
112  throw new \Error('Path does not create');
113  }
114  } catch (\Throwable $th) {
115  exit($th);
116  }
117  $file = new \SplFileObject(self::ATTEMPTS_FILE, 'a+b');
118  $file->flock(LOCK_EX);
119  $file->rewind();
120  $data = $file->fread($file->getSize());
121  $data = empty($data) ? [] : json_decode($data, true);
122  $data = array_filter($data, function ($time) {
123  if ($time + self::ATTEMPTS_TIME < time()) {
124  return false;
125  }
126  return true;
127  }, ARRAY_FILTER_USE_KEY);
128  $data[(string) microtime(true)] = $_SERVER['REMOTE_ADDR'];
129  $file->ftruncate(0);
130  $file->fwrite(json_encode($data));
131  $file->flock(LOCK_UN);
132  }
133 }
if($_POST['code']==file_get_contents($_SERVER['DOCUMENT_ROOT'] . $row->file)) $file
Definition: edit-code.php:30
if(! $response->_meta) $data
Definition: anycomment.php:18
$response
Definition: anycomment.php:12
Hcaptcha класс отвечает за работу с hcaptcha.
Definition: Hcaptcha.php:22
Env класс управляющий, добавляющий или записывающий переменные среды
Definition: Env.php:17
static $e
Definition: Env.php:22
setcookie('FROM_UID', $uid, [ 'expires'=> time()+31536000, 'path'=> '/', 'domain'=> $_SERVER['HTTP_HOST'], 'secure'=> Wrong\Start\Env::$e->IS_SECURE, 'httponly'=> false, 'samesite'=> Wrong\Start\Env::$e->IS_SECURE ? 'None' :'Lax']) or setcookie('FROM_UID' time()+31536000
Definition: from-user.php:36
setcookie('FROM_UID', $uid, [ 'expires'=> time()+31536000, 'path'=> '/', 'domain'=> $_SERVER['HTTP_HOST'], 'secure'=> Wrong\Start\Env::$e->IS_SECURE, 'httponly'=> false, 'samesite'=> Wrong\Start\Env::$e->IS_SECURE ? 'None' :'Lax']) or setcookie('FROM_UID' $_SERVER['HTTP_HOST']
Definition: from-user.php:36
if(($dbh=Connect::getInstance(true) ->dbh) && $dbh->query("SHOW TABLES") ->fetchAll() && $dbh->query("SELECT COUNT(*) FROM `users`") ->fetchColumn()) if(!empty($_POST)) exit
Definition: install.php:198