thinkphp實現圖像驗證碼

示例

在這里插入圖片描述

服務類 app\common\lib\captcha

<?php
namespace app\common\lib\captcha;use think\facade\Cache;
use think\facade\Config;
use Exception;class Captcha
{private $im = null; // 驗證碼圖片實例private $color = null; // 驗證碼字體顏色// 默認配置protected $config = ['length'      => 4,      // 驗證碼位數'fontSize'    => 25,     // 字體大小(px)'imageH'      => 0,      // 驗證碼高度'imageW'      => 0,      // 驗證碼寬度'useCurve'    => true,   // 是否畫混淆曲線'useNoise'    => false,  // 是否添加雜點(已禁用)'bg'          => [243, 251, 254], // 背景顏色'fontttf'     => '',     // 字體文件路徑'useZh'       => false,  // 使用中文驗證碼'math'        => false,  // 算術驗證碼'alpha'       => 0,      // 透明度(0-127)'api'         => false,  // API模式'fontPath'    => '',     // 字體文件目錄'bgPath'      => '',     // 背景圖片目錄'expire'      => 1800,   // 驗證碼過期時間(s)];// 簡化后的驗證碼字符集合(僅數字和大寫字母)protected $codeSet = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ';/*** 構造函數* @param array $config 配置參數*/public function __construct(array $config = []){// 合并配置參數$this->config = array_merge($this->config, Config::get('captcha', []), $config);// 設置字體路徑if (empty($this->config['fontPath'])) {$this->config['fontPath'] = __DIR__ . '/ttfs/';}}/*** 生成驗證碼* @param string $uniqueId 前端傳遞的唯一標識(如時間戳)* @return string 圖片二進制內容*/public function create(string $uniqueId = ''): string{// 清理過期緩存$this->clearExpiredCaptchas();// 如果未提供 uniqueId,則生成一個默認值if (empty($uniqueId)) {$uniqueId = uniqid('captcha_');}// 生成驗證碼文本$generator = $this->generate($uniqueId);// 計算圖片寬高$this->config['imageW'] = $this->config['imageW'] ?: $this->config['length'] * $this->config['fontSize'] * 1.5;$this->config['imageH'] = $this->config['imageH'] ?: $this->config['fontSize'] * 2;// 創建圖片資源$this->im = imagecreate((int)$this->config['imageW'], (int)$this->config['imageH']);// 設置背景色$bgColor = imagecolorallocate($this->im,$this->config['bg'][0],$this->config['bg'][1],$this->config['bg'][2]);imagefill($this->im, 0, 0, $bgColor);// 設置字體顏色$this->color = imagecolorallocate($this->im, mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100));// 添加干擾線if ($this->config['useCurve']) {$this->writeCurve();}// 繪制驗證碼$text = str_split($generator['value']);$space = $this->config['imageW'] / $this->config['length'];foreach ($text as $index => $char) {// 計算位置$x = $space * $index + mt_rand(5, 10);$y = $this->config['imageH'] / 2 + $this->config['fontSize'] / 2;$angle = mt_rand(-15, 15);imagettftext($this->im,(int)$this->config['fontSize'],$angle,(int)$x,(int)$y,$this->color,$this->getFont(),$char);}ob_start();imagepng($this->im);$content = ob_get_clean();imagedestroy($this->im);return $content;}/*** 驗證驗證碼* @param string $code 用戶輸入的驗證碼* @param string $uniqueId 前端傳遞的唯一標識(如時間戳)* @return bool*/public function check(string $code, string $uniqueId = ''): bool{if (empty($uniqueId)) {return false;}// 從 Cache 中獲取數據$cacheData = Cache::get($uniqueId);if (!$cacheData || time() - $cacheData['time'] > $this->config['expire']) {$this->removeCaptchaFromRecords($uniqueId);return false;}// 驗證碼校驗$result = password_verify(strtoupper($code), $cacheData['key']);return $result;}/*** 生成驗證碼文本* @param string $uniqueId 前端傳遞的唯一標識(如時間戳)* @return array ['value' => 顯示的文本, 'key' => 加密后的驗證碼]*/protected function generate(string $uniqueId): array{$bag = '';$characters = str_split($this->codeSet);for ($i = 0; $i < $this->config['length']; $i++) {$bag .= $characters[random_int(0, count($characters) - 1)];}$key = strtoupper($bag);// 使用 Bcrypt 加密驗證碼$hash = password_hash($key, PASSWORD_BCRYPT, ['cost' => 10]);// 將驗證碼信息存儲到 Cache 中Cache::set($uniqueId, ['key' => $hash,'time' => time(),// 'raw' => $key // 調試用,正式環境移除], $this->config['expire']);// 記錄到清理隊列$this->addCaptchaToRecords($uniqueId);return ['value' => $bag, 'key' => $hash];}/*** 添加驗證碼記錄到清理隊列*/protected function addCaptchaToRecords(string $uniqueId): void{$records = Cache::get('captcha_records', []);$records[$uniqueId] = time() + $this->config['expire'];// 限制最大記錄數,防止內存占用過大if (count($records) > 1000) {$records = array_slice($records, -500, null, true);}Cache::set('captcha_records', $records);}/*** 從清理隊列中移除驗證碼記錄*/protected function removeCaptchaFromRecords(string $uniqueId): void{$records = Cache::get('captcha_records', []);unset($records[$uniqueId]);Cache::set('captcha_records', $records);}/*** 清理過期的驗證碼緩存*/protected function clearExpiredCaptchas(): void{// 每小時清理一次$lastClear = Cache::get('last_captcha_clear', 0);if (time() - $lastClear < 3600) {return;}$records = Cache::get('captcha_records', []);$now = time();$cleaned = false;foreach ($records as $uid => $expireTime) {if ($expireTime < $now) {Cache::delete($uid);unset($records[$uid]);$cleaned = true;}}if ($cleaned) {Cache::set('captcha_records', $records);Cache::set('last_captcha_clear', time());}}/*** 獲取字體文件路徑* @return string* @throws Exception*/protected function getFont(): string{if (!empty($this->config['fontttf'])) {return $this->config['fontttf'];}$fonts = glob($this->config['fontPath'] . '*.ttf') +glob($this->config['fontPath'] . '*.otf');if (empty($fonts)) {throw new Exception('驗證碼字體文件不存在,請檢查字體路徑: ' . $this->config['fontPath']);}return $fonts[array_rand($fonts)];}/*** 畫干擾曲線*/protected function writeCurve(): void{$px = $py = 0;// 曲線前部分$A = mt_rand(1, (int)($this->config['imageH'] / 2)); // 振幅$b = mt_rand((int)(-$this->config['imageH'] / 4), (int)($this->config['imageH'] / 4)); // Y軸偏移$f = mt_rand((int)(-$this->config['imageH'] / 4), (int)($this->config['imageH'] / 4)); // X軸偏移$T = mt_rand($this->config['imageH'], $this->config['imageW'] * 2); // 周期$w = (2 * M_PI) / $T;$px1 = 0; // 起始X坐標$px2 = mt_rand((int)($this->config['imageW'] / 2), (int)($this->config['imageW'] * 0.8)); // 結束X坐標for ($px = $px1; $px <= $px2; $px++) {if ($w != 0) {$py = $A * sin($w * $px + $f) + $b + $this->config['imageH'] / 2;$i = (int)($this->config['fontSize'] / 5);while ($i > 0) {imagesetpixel($this->im, $px + $i, $py + $i, $this->color);$i--;}}}// 曲線后部分$A = mt_rand(1, (int)($this->config['imageH'] / 2));$f = mt_rand((int)(-$this->config['imageH'] / 4), (int)($this->config['imageH'] / 4));$T = mt_rand($this->config['imageH'], $this->config['imageW'] * 2);$w = (2 * M_PI) / $T;$b = $py - $A * sin($w * $px + $f) - $this->config['imageH'] / 2;$px1 = $px2;$px2 = $this->config['imageW'];for ($px = $px1; $px <= $px2; $px++) {if ($w != 0) {$py = $A * sin($w * $px + $f) + $b + $this->config['imageH'] / 2;$i = (int)($this->config['fontSize'] / 5);while ($i > 0) {imagesetpixel($this->im, $px + $i, $py + $i, $this->color);$i--;}}}}
}

控制器調用

// 生成圖形驗證碼public function getCaptcha(){$uid = 'captcha_' . uniqid('', true);$captcha = new \app\common\lib\captcha\Captcha();$img = $captcha->create($uid);return json(['image' => 'data:image/png;base64,'.base64_encode($img),'uid' => $uid]);}// 校驗圖形驗證碼public function checkCaptcha(){$code = input('post.code');$uid = input('post.uid');$captcha = new \app\common\lib\captcha\Captcha();$result = $captcha->check($code, $uid);return json(['success' => $result,'input_code' => $code,'uid' => $uid]);}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/77554.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/77554.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/77554.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

swift-12-Error處理、關聯類型、assert、泛型_

一、錯誤類型 開發過程常見的錯誤 語法錯誤&#xff08;編譯報錯&#xff09; 邏輯錯誤 運行時錯誤&#xff08;可能會導致閃退&#xff0c;一般也叫做異常&#xff09; 2.1 通過結構體 第一步 struct MyError : Errort { var msg: String &#xff5d; 第二步 func divide(_ …

實驗擴充 LED顯示4*4鍵位值

代碼功能概述 鍵盤掃描&#xff1a; 使用 KeyPort&#xff08;定義為 P1&#xff09;作為鍵盤輸入端口。掃描 4x4 矩陣鍵盤&#xff0c;檢測按鍵并返回按鍵編號&#xff08;0~15&#xff09;。 數碼管顯示&#xff1a; 根據按鍵編號&#xff0c;從 SegCode 數組中獲取對應數碼…

從零開始搭建CLIP模型實現基于文本的圖像檢索

目錄 CLIP原理簡介代碼實現參考鏈接 CLIP原理簡介 論文鏈接&#xff0c;源碼鏈接 CLIP模型由OpenAI在2021年提出&#xff0c;利用雙Decoder&#xff08;Dual Encoder&#xff09;的架構來學習圖像和文本之間的對應關系&#xff0c;是多模態大模型的開創之作&#xff0c;為后續許…

熊海cms代碼審計

目錄 sql注入 1. admin/files/login.php 2. admin/files/columnlist.php 3. admin/files/editcolumn.php 4. admin/files/editlink.php 5. admin/files/editsoft.php 6. admin/files/editwz.php 7. admin/files/linklist.php 8. files/software.php 9. files…

[Java微服務組件]注冊中心P3-Nacos中的設計模式1-觀察者模式

在P1-簡單注冊中心實現和P2-Nacos解析中&#xff0c;我們分別實現了簡單的注冊中心并總結了Nacos的一些設計。 本篇繼續看Nacos源碼&#xff0c;了解一下Nacos中的設計模式。 目錄 Nacos 觀察者模式 Observer Pattern觀察者模式總結 Nacos 觀察者模式 Observer Pattern 模式定…

電腦 訪問 github提示 找不到網頁,處理方案

1、找到 本機的 host文件 例如 windows 的 一般在 C:\Windows\System32\drivers\etc\hosts 用管理員身份打開 hosts 文件 如果文件中沒有 github的配置&#xff0c;需要自己手動添加上去&#xff1b; 如果有&#xff0c;則需要 檢查 github.com 與 github.global.ssl.fastly.…

Linux系統中的網絡管理

1.RHEL9版本中&#xff0c;使用nm進行網絡配置&#xff0c;ifcfg不再是網絡配置文件的主存儲&#xff0c;樣式仍然可用&#xff0c;但它不再是NetworkManger存儲新網絡配置文件的默認位置&#xff0c;RHEL以key-file格式在etc/NetworkManger/system-connections/中存儲新的網絡…

AI技術深度解析:從移動芯片到AIoT的全面突破

作為全球無線通信技術和半導體解決方案的重要參與者,高通始終將技術創新作為核心驅動力,在移動通信、物聯網(IoT)、汽車電子、AI計算等領域占據關鍵地位。本文將從其核心產品線、技術突破、應用場景及未來布局四個維度,客觀解析高通的技術積累與行業角色。 一、核心產品線…

使用CS Roofline Toolkit測量帶寬

使用CS Roofline Toolkit測量帶寬 工程下載&#xff1a;使用CS Roofline Toolkit測量帶寬-案例工程文件&#xff0c;也可以按照下面的說明使用git clone下載 目錄 使用CS Roofline Toolkit測量帶寬0、Roofline模型理解1、CS Roofline Toolkit下載1.1、設置代理1.2、git clone下…

EAGLE代碼研讀+模型復現

要對代碼下手了&#xff0c;加油(? ?_?)? 作者在他們自己的設備上展現了推理的評估結果&#xff0c;受第三方評估認證&#xff0c;EAGLE為目前最快的投機方法&#xff08;雖然加速度是評估投機解碼方法的主要指標&#xff0c;但其他點也值得關注。比如PLD和Lookahead無需額…

基于SFC的windows修復程序,修復絕大部分系統損壞

效果:可以自動修復大部分由系統文件損壞而導致的錯誤 例如:系統應用無法打開 系統窗口(例如開始菜單)無法使用 電腦藍屏或者卡死.....文章 01技術背景 Windows自帶了一個SFC命令行應用程序,可以檢查大部分的系統文件錯誤,以及復這些文件 其中自動檢查所有系統文件&#x…

liunx日志問題

一、日志定向 Linux 系統的日志配置文件&#xff08;如/etc/syslog.conf或/etc/rsyslog.conf &#xff09;中&#xff0c;用于定義系統日志的記錄規則&#xff0c;決定哪些類型的日志消息會被記錄到特定的日志文件中。 *.info;mail.none;authpriv.none;cron.none /va…

2.凸包優化求解

1.減而治之(Decrease and Conquer) 插入排序 典型的減而治之算法就是插入排序方法 插入排序法: 在未排序中選擇一個元素&#xff0c;插入到已經排序號的序列中 將凸包也采用減而治之的方法 2.In-Convex-Polygon Test 怎么判斷引入的極點存在于多邊形里面還是外面&#xff1…

系統思考:危機中的轉型機遇

“危機不僅是挑戰&#xff0c;更是轉型的機會” 每當大事發生&#xff0c;很多企業老板常常被眼前的困境壓得喘不過氣&#xff0c;焦慮與壓力讓人難以思考長遠。特別是在危機面前&#xff0c;大家忙于應對眼前的風險&#xff0c;卻忽略了背后隱藏的機遇。而危機&#xff0c;恰…

大模型Rag - 如何評估Rag

一.RAG流程與評估標準補充 RAG&#xff08;Retrieval-Augmented Generation&#xff09;是一種結合檢索與生成的問答架構。為了確保系統效果&#xff0c;需要從以下三個角度對其評估&#xff1a; 回顧RAG流程 用戶提出問題 → 系統檢索相關上下文 → 基于上下文由大語言模型…

Linux RT RT RT

RT的最終目的是盡可能多的讓原來系統不可搶占的部分變成可搶占&#xff0c;讓高優先級的程序先跑。這里的rt引入了一個deadline的說法&#xff0c;此時的實時性是保證在最大一個時間間隔內&#xff0c;程序被執行。比如每100ms算法做一次決策。 所以此時面臨著幾座大山…

演員柳琦正式加入創星演員出道計劃,開創演藝事業新天地

4月18日&#xff0c;演員柳琦正式加入“創星演員出道計劃”&#xff0c;不僅得到參演都市愛情喜劇《和我結婚吧》角色的機會&#xff0c;還獲得文旅精品網劇《醉夢靈州》的出演機會&#xff0c;自此開啟全新影視之路。對表演藝術極具天賦的柳琦&#xff0c;相信未來可以憑借自身…

16.Chromium指紋瀏覽器開發教程之WebGPU指紋定制

WebGPU指紋概述 WebGPU是下一代的Web圖形和計算API&#xff0c;旨在提供高性能的圖形渲染和計算能力。它是WebGL的后繼者&#xff0c;旨在利用現代GPU的強大功能&#xff0c;使得Web應用能夠實現接近原生應用的圖形和計算性能。而且它是一個低級別的API&#xff0c;可以直接與…

HTTP:九.WEB機器人

概念 Web機器人是能夠在無需人類干預的情況下自動進行一系列Web事務處理的軟件程序。人們根據這些機器人探查web站點的方式,形象的給它們取了一個飽含特色的名字,比如“爬蟲”、“蜘蛛”、“蠕蟲”以及“機器人”等!爬蟲概述 網絡爬蟲(英語:web crawler),也叫網絡蜘蛛(…

Vue3+TS中svg圖標的使用

安裝依賴 pnpm i vite-plugin-svg-icons -D配置引入 vite.config.ts ... import { createSvgIconsPlugin } from vite-plugin-svg-icons import path from node:pathconst svgIconsPlugin createSvgIconsPlugin({iconDirs: [path.resolve(process.cwd(), src/assets/icons)]…