Captcha.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. <?php
  2. declare(strict_types=1);
  3. //TODO: 打个标记 下次一定改静态类(
  4. namespace Sakura\API;
  5. class Captcha
  6. {
  7. private $captchCode;
  8. /**
  9. * CAPTCHA constructor.
  10. */
  11. public function __construct()
  12. {
  13. $this->captchCode = '';
  14. }
  15. /**
  16. * create_captcha
  17. *
  18. * @return void
  19. */
  20. private function create_captcha(): void
  21. {
  22. $dict = str_split('abcdefhjkmnpqrstuvwxy12345678');
  23. $randKeys = array_rand($dict, 5);
  24. $this->captchCode = implode('', array_map(function ($value) use ($dict) {
  25. return $dict[$value];
  26. }, $randKeys));
  27. }
  28. /**
  29. * crypt_captcha
  30. *
  31. * @return string
  32. */
  33. private function crypt_captcha(): string
  34. {
  35. //return md5($this->captchCode);
  36. return password_hash($this->captchCode, PASSWORD_DEFAULT);
  37. // return wp_hash_password($this->captchCode);
  38. }
  39. /**
  40. * verify_captcha
  41. *
  42. * @param string $captcha
  43. * @param string $hash
  44. * @return bool
  45. */
  46. public function verify_captcha(string $captcha, string $hash): bool
  47. {
  48. //return md5($captcha) == $hash ? true : false;
  49. return password_verify($captcha, $hash);
  50. // return wp_check_password($captcha, $hash);
  51. }
  52. /**
  53. * create_captcha_img
  54. *
  55. * @return array
  56. */
  57. public function create_captcha_img(): array
  58. {
  59. //创建画布
  60. $img = imagecreatetruecolor(120, 40);
  61. $file = STYLESHEETPATH . '/inc/KumoFont.ttf';
  62. //填充背景色
  63. $backcolor = imagecolorallocate($img, mt_rand(200, 255), mt_rand(200, 255), mt_rand(0, 255));
  64. imagefill($img, 0, 0, $backcolor);
  65. //创建验证码
  66. $this->create_captcha();
  67. //绘制文字
  68. for ($i = 0; $i < 5; $i++) {
  69. // $span = 20;
  70. $stringcolor = imagecolorallocate($img, mt_rand(0, 255), mt_rand(0, 100), mt_rand(0, 80));
  71. imagefttext($img, 25, 2, $i * 20, 30, $stringcolor, $file, $this->captchCode[$i]);
  72. }
  73. //添加干扰线
  74. for ($i = 0; $i < 8; $i++) {
  75. $linecolor = imagecolorallocate($img, mt_rand(0, 150), mt_rand(0, 250), mt_rand(0, 255));
  76. imageline($img, mt_rand(0, 179), mt_rand(0, 39), mt_rand(0, 179), mt_rand(0, 39), $linecolor);
  77. }
  78. //添加干扰点
  79. for ($i = 0; $i < 144; $i++) {
  80. $pixelcolor = imagecolorallocate($img, mt_rand(100, 150), mt_rand(0, 120), mt_rand(0, 255));
  81. imagesetpixel($img, mt_rand(0, 179), mt_rand(0, 39), $pixelcolor);
  82. }
  83. $timestamp = time();
  84. $this->captchCode .= $timestamp;
  85. //打开缓存区
  86. ob_start();
  87. imagepng($img);
  88. //输出图片
  89. $captchaimg = ob_get_contents();
  90. //销毁缓存区
  91. ob_end_clean();
  92. //销毁图片(释放资源)
  93. imagedestroy($img);
  94. // 以json格式输出
  95. $captchaimg = 'data:image/png;base64,' . base64_encode($captchaimg);
  96. return [
  97. 'code' => 0,
  98. 'data' => $captchaimg,
  99. 'msg' => '',
  100. 'id' => $this->crypt_captcha(),
  101. 'time' => $timestamp,
  102. ];
  103. }
  104. /**
  105. * check_captcha
  106. *
  107. * @param string $captcha
  108. * @return array
  109. */
  110. public function check_captcha(string $captcha, int $timestamp, string $id): array
  111. {
  112. $currentTime = time();
  113. $timeThreshold = $currentTime - 60;
  114. if (!isset($timestamp) || !isset($id) || !preg_match('/^[\w$.\/]+$/', $id) || !ctype_digit((string)$timestamp)) {
  115. $code = 3;
  116. $msg = __('Bad Request.',"sakurairo");//非法请求
  117. } elseif (empty($captcha) || strlen($captcha) !== 5) {
  118. $code = 3;
  119. $msg = __("Look like you forgot to enter the captcha.","sakurairo");//请输入正确的验证码!
  120. } elseif ($timestamp < $timeThreshold) {
  121. $code = 2;
  122. $msg = __("Captcha timeout.","sakurairo");//超时!
  123. } elseif ($timestamp >= $timeThreshold && $timestamp <= $currentTime) {
  124. if ($this->verify_captcha($captcha . $timestamp, $id)) {
  125. $code = 5;
  126. $msg = __("Captcha check passed.","sakurairo");//'验证码正确!'
  127. } else {
  128. $code = 1;
  129. $msg = __("Captcha incorrect.","sakurairo");//'验证码错误!'
  130. }
  131. } else {
  132. $code = 1;
  133. $msg = __("An error has occurred.","sakurairo");//'错误!'
  134. }
  135. return [
  136. 'code' => $code,
  137. 'data' => '',
  138. 'msg' => $msg
  139. ];
  140. }
  141. }