找回密码
 注册
搜索
免费空间 免费域名 免费AI 老牌主机商首月仅1美分!27美元/年!Spaceship优惠码 Namecheap优惠码阿里云2核2G3M新老续费同享99元/年!
楼主: jason

[程序代码] typecho有没有登录验证码插件?

[复制链接]
发表于 2024-11-30 16:15:18 | 显示全部楼层
jason 发表于 2024-11-29 00:07
不能用,beget空间,永远都是    验证码错误

Plugin.php
  1. <?php

  2. namespace TypechoPlugin\LoginCaptcha;

  3. use Typecho\Common;
  4. use Typecho\Cookie;
  5. use Typecho\Plugin\PluginInterface;
  6. use Typecho\Widget\Helper\Form;
  7. use Typecho\Request as HttpRequest;
  8. use Typecho\Response as HttpResponse;
  9. use Typecho\Widget\Request;
  10. use Typecho\Widget\Response;
  11. use Utils\Helper;
  12. use Widget\Notice;

  13. if (!defined('__TYPECHO_ROOT_DIR__')) exit;
  14. /**
  15. * Typecho 后台登录页面增加验证码保护
  16. *
  17. * @package LoginCaptcha
  18. * @author Ryan
  19. * @version 1.0.1
  20. * @link https://doufu.ru
  21. *
  22. */
  23. class Plugin implements PluginInterface
  24. {
  25.     public static function activate()
  26.     {
  27.         \Typecho\Plugin::factory('index.php')->begin = [__CLASS__, 'hookRoute'];
  28.         Helper::addRoute('login-captcha', '/login-captcha', Action::class, 'renderCaptcha');
  29.         \Typecho\Plugin::factory('admin/footer.php')->end = [__CLASS__, 'addCaptcha'];
  30.     }

  31.     public static function deactivate()
  32.     {
  33.         Helper::removeRoute('login-captcha');
  34.     }

  35.     public static function config(Form $form)
  36.     {
  37.         // 插件配置项
  38.     }

  39.     public static function personalConfig(Form $form)
  40.     {
  41.         // 个人配置项
  42.     }

  43.     public static function hookRoute()
  44.     {
  45.         $request = new Request(HttpRequest::getInstance());
  46.         $response = new Response(HttpRequest::getInstance(), HttpResponse::getInstance());
  47.         $pathinfo = $request->getPathInfo();
  48.         
  49.         // Ensure session is started
  50.         if (session_status() == PHP_SESSION_NONE) {
  51.             session_start();
  52.         }

  53.         if (preg_match("#/action/login#", $pathinfo)) {
  54.             if (!isset($_SESSION['captcha']) || intval($_POST['captcha']) != $_SESSION['captcha']) {
  55.                 Notice::alloc()->set(_t('验证码错误'), 'error');
  56.                 Cookie::set('__typecho_remember_captcha', '');
  57.                 $response->goBack();
  58.             }
  59.         }
  60.     }

  61.     public static function addCaptcha()
  62.     {
  63.         $request = new Request(HttpRequest::getInstance());
  64.         $pathinfo = $request->getRequestUri();
  65.         $loginPath = Common::url('login.php', defined('__TYPECHO_ADMIN_DIR__') ? __TYPECHO_ADMIN_DIR__ : '/admin/');
  66.         $secureUrl = Helper::security()->getIndex('login-captcha');
  67.         if (stripos($pathinfo, $loginPath) === 0) {
  68.             ?>
  69.             <script>
  70.                 (function () {
  71.                     let _src = '<?php echo $secureUrl ?>';
  72.                     const src = _src + (_src.includes('?') ? '&t=' : '?t=');
  73.                     let pwd = document.getElementById('password');
  74.                     pwd?.parentNode?.insertAdjacentHTML('afterend', `<p id="captcha-section">
  75.                         <label class="sr-only" for="captcha"><?php _e("验证码"); ?></label>
  76.                         <input type="text" name="captcha" id="captcha" class="text-l w-100" placeholder="<?php _e("验证码答案"); ?>" required />
  77.                         <img id="captcha-img" src="<?php echo $secureUrl ?>" title="<?php _e("点击刷新") ?>" />
  78.                     </p>`);
  79.                     let img = document.getElementById('captcha-img');
  80.                     let timeOut;
  81.                     img?.addEventListener('click', function () {
  82.                         if (img.classList.contains('not-allow')) {
  83.                             return;
  84.                         }
  85.                         img.classList.add('not-allow');
  86.                         img.src = src + Math.random();
  87.                         timeOut = setTimeout(() => {
  88.                             img.classList.remove('not-allow');
  89.                         }, 1000);
  90.                     });
  91.                 })()
  92.             </script>
  93.             <style>
  94.                 #captcha-section {
  95.                     display: flex;
  96.                 }

  97.                 #captcha {
  98.                     box-sizing: border-box;
  99.                 }

  100.                 #captcha:invalid:not(:placeholder-shown) {
  101.                     border: 2px solid red; /* 不符合模式时显示红框 */
  102.                 }

  103.                 #captcha:valid {
  104.                     border: 2px solid green; /* 符合模式时显示绿框 */
  105.                 }

  106.                 #captcha-img {
  107.                     cursor: pointer;
  108.                 }

  109.                 #captcha-img.not-allow {
  110.                     cursor: not-allowed;
  111.                 }
  112.             </style>
  113.             <?php
  114.         }
  115.     }
  116. }
复制代码


Action.php
  1. <?php

  2. namespace TypechoPlugin\LoginCaptcha;

  3. use Typecho\Widget;
  4. use Utils\Helper;
  5. use Widget\ActionInterface;

  6. class Action extends Widget implements ActionInterface
  7. {
  8.     public function renderCaptcha()
  9.     {
  10.         Helper::security()->protect();
  11.         
  12.         // Ensure session is started
  13.         if (session_status() == PHP_SESSION_NONE) {
  14.             session_start();
  15.         }

  16.         $captcha = $this->generateCaptcha();
  17.         $_SESSION['captcha'] = $captcha['code'];
  18.         header('Content-type: image/png');
  19.         imagepng($captcha['image']);
  20.         imagedestroy($captcha['image']);
  21.         exit;
  22.     }

  23.     private function generateCaptcha(): array
  24.     {
  25.         $num1 = rand(10, 99); // 两位数
  26.         $num2 = rand(10, 99); // 两位数
  27.         $code = $num1 + $num2;
  28.         $question = "$num1 + $num2 = ?";

  29.         $width = 100;
  30.         $height = 30;
  31.         $image = imagecreatetruecolor($width, $height);

  32.         // Enable transparency
  33.         imagealphablending($image, false);
  34.         imagesavealpha($image, true);

  35.         // Allocate a transparent background
  36.         $background_color = imagecolorallocatealpha($image, 255, 255, 255, 127);
  37.         imagefill($image, 0, 0, $background_color);

  38.         // Add noise to the background with random colors
  39.         for ($i = 0; $i < 100; $i++) {
  40.             $noise_color = imagecolorallocate($image, rand(100, 255), rand(100, 255), rand(100, 255));
  41.             imagesetpixel($image, rand(0, $width), rand(0, $height), $noise_color);
  42.         }

  43.         $text_color = imagecolorallocate($image, rand(0, 255), rand(0, 255), rand(0, 255));
  44.         imagettftext($image, 20, 0, 10, 25, $text_color, dirname(__FILE__) . DIRECTORY_SEPARATOR . 'c7a6aeea915a139782e569aaaf55a5aa.ttf', $question);

  45.         return array('image' => $image, 'code' => $code);
  46.     }

  47.     public function action()
  48.     {
  49.         // Empty action method
  50.     }
  51. }
复制代码
发表于 2024-11-30 16:28:08 | 显示全部楼层
本帖最后由 yaner 于 2024-11-30 16:29 编辑
efc88ff45580620 发表于 2024-11-29 00:20
我也是,无法登录了

Action.php   验证码更新为汉字一位数加法

  1. <?php

  2. namespace TypechoPlugin\LoginCaptcha;

  3. use Typecho\Widget;
  4. use Utils\Helper;
  5. use Widget\ActionInterface;

  6. class Action extends Widget implements ActionInterface
  7. {
  8.     public function renderCaptcha()
  9.     {
  10.         Helper::security()->protect();
  11.         
  12.         // Ensure session is started
  13.         if (session_status() == PHP_SESSION_NONE) {
  14.             session_start();
  15.         }

  16.         $captcha = $this->generateCaptcha();
  17.         $_SESSION['captcha'] = $captcha['code'];
  18.         header('Content-type: image/png');
  19.         imagepng($captcha['image']);
  20.         imagedestroy($captcha['image']);
  21.         exit;
  22.     }

  23.     private function generateCaptcha(): array
  24.     {
  25.         $num1 = rand(1, 9); // 一位数
  26.         $num2 = rand(1, 9); // 一位数
  27.         $code = $num1 + $num2;
  28.         $question = $this->numberToChinese($num1) . " + " . $this->numberToChinese($num2) . " = ?";

  29.         $width = 200; // Adjusted width for longer text
  30.         $height = 30;
  31.         $image = imagecreatetruecolor($width, $height);

  32.         // Enable transparency
  33.         imagealphablending($image, false);
  34.         imagesavealpha($image, true);

  35.         // Allocate a transparent background
  36.         $background_color = imagecolorallocatealpha($image, 255, 255, 255, 127);
  37.         imagefill($image, 0, 0, $background_color);

  38.         // Add noise to the background with random colors
  39.         for ($i = 0; $i < 100; $i++) {
  40.             $noise_color = imagecolorallocate($image, rand(100, 255), rand(100, 255), rand(100, 255));
  41.             imagesetpixel($image, rand(0, $width), rand(0, $height), $noise_color);
  42.         }

  43.         $text_color = imagecolorallocate($image, rand(0, 255), rand(0, 255), rand(0, 255));
  44.         imagettftext($image, 20, 0, 10, 25, $text_color, dirname(__FILE__) . DIRECTORY_SEPARATOR . 'hylxjt.ttf', $question);

  45.         return array('image' => $image, 'code' => $code);
  46.     }

  47.     private function numberToChinese($num)
  48.     {
  49.         $chineseNumbers = array('零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖');
  50.         return $chineseNumbers[$num];
  51.     }

  52.     public function action()
  53.     {
  54.         // Empty action method
  55.     }
  56. }
复制代码


附带瘦身的字体文件





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×

评分

参与人数 1银币 +20 收起 理由
efc88ff45580620 + 20 很给力!

查看全部评分

发表于 2024-11-30 17:00:36 | 显示全部楼层
本帖最后由 yaner 于 2024-11-30 17:06 编辑

Action.php  更新为汉字、数字随机显示一位数加法

  1. <?php

  2. namespace TypechoPlugin\LoginCaptcha;

  3. use Typecho\Widget;
  4. use Utils\Helper;
  5. use Widget\ActionInterface;

  6. class Action extends Widget implements ActionInterface
  7. {
  8.     public function renderCaptcha()
  9.     {
  10.         Helper::security()->protect();
  11.         
  12.         // Ensure session is started
  13.         if (session_status() == PHP_SESSION_NONE) {
  14.             session_start();
  15.         }

  16.         $captcha = $this->generateCaptcha();
  17.         $_SESSION['captcha'] = $captcha['code'];
  18.         header('Content-type: image/png');
  19.         imagepng($captcha['image']);
  20.         imagedestroy($captcha['image']);
  21.         exit;
  22.     }

  23.     private function generateCaptcha(): array
  24.     {
  25.         $num1 = rand(1, 9); // 一位数
  26.         $num2 = rand(1, 9); // 一位数
  27.         $code = $num1 + $num2;

  28.         $num1Chinese = $this->numberToChinese($num1);
  29.         $num2Chinese = $this->numberToChinese($num2);

  30.         // 随机选择阿拉伯数字和汉字显示,保证至少有一个是汉字
  31.         $rand = rand(0, 2);
  32.         if ($rand == 0) {
  33.             $question = "$num1 + $num2Chinese=?";
  34.         } elseif ($rand == 1) {
  35.             $question = "$num1Chinese + $num2=?";
  36.         } else {
  37.             $question = "$num1Chinese + $num2Chinese=?";
  38.         }

  39.         $width = 170; // Fixed width
  40.         $height = 50; // Fixed height
  41.         $image = imagecreatetruecolor($width, $height);

  42.         // Enable transparency
  43.         imagealphablending($image, false);
  44.         imagesavealpha($image, true);

  45.         // Allocate a transparent background
  46.         $background_color = imagecolorallocatealpha($image, 255, 255, 255, 127);
  47.         imagefill($image, 0, 0, $background_color);

  48.         // Add noise to the background with random colors
  49.         for ($i = 0; $i < 100; $i++) {
  50.             $noise_color = imagecolorallocate($image, rand(100, 255), rand(100, 255), rand(100, 255));
  51.             imagesetpixel($image, rand(0, $width), rand(0, $height), $noise_color);
  52.         }

  53.         // Add interference lines
  54.         for ($i = 0; $i < 5; $i++) {
  55.             $line_color = imagecolorallocate($image, rand(100, 255), rand(100, 255), rand(100, 255));
  56.             imageline($image, rand(0, $width), rand(0, $height), rand(0, $width), rand(0, $height), $line_color);
  57.         }

  58.         // Calculate the position to ensure the text is centered in the middle 80% area
  59.         $textbox = imagettfbbox(20, 0, dirname(__FILE__) . DIRECTORY_SEPARATOR . 'hylxjt.ttf', $question);
  60.         $text_width = $textbox[2] - $textbox[0];
  61.         $text_height = $textbox[7] - $textbox[1];
  62.         $x = ($width - $text_width) / 2; // Center horizontally
  63.         $y = ($height - $text_height) / 2; // Center vertically and adjust for font size

  64.         $text_color = imagecolorallocate($image, rand(0, 255), rand(0, 255), rand(0, 255));
  65.         imagettftext($image, 20, 0, $x, $y, $text_color, dirname(__FILE__) . DIRECTORY_SEPARATOR . 'hylxjt.ttf', $question);

  66.         return array('image' => $image, 'code' => $code);
  67.     }

  68.     private function numberToChinese($num)
  69.     {
  70.         $chineseNumbers = array('零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖');
  71.         return $chineseNumbers[$num];
  72.     }

  73.     public function action()
  74.     {
  75.         // Empty action method
  76.     }
  77. }
复制代码




感谢豆腐ru的基础代码,我就是瞎搞一下,不保证安全性,也不能自定义配置。
主要是记录在这,万一哪 天自用需要


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
发表于 2024-11-30 17:20:31 | 显示全部楼层
yaner 发表于 2024-11-30 17:00
Action.php  更新为汉字、数字随机显示一位数加法

目前确实不能自定义,后续可以合并起来做成插件模式,等我有空再说
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|小黑屋|免费吧论坛

GMT+8, 2024-12-12 00:43 , Processed in 0.024255 second(s), 4 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表