如何使用PHP创建图像验证码

张开发
2026/4/3 13:41:01 15 分钟阅读
如何使用PHP创建图像验证码
如何使用PHP创建图像验证码PHP 图像验证码的实现完全基于GD 库它是 PHP 官方内置的图像处理扩展提供了画布创建、颜色分配、文本绘制、图形渲染、图片输出等全能力是 PHP 图像处理的行业标准方案。开启 GD 扩展Windows 环境打开php.ini去掉extensiongd前的分号注释重启 Web 服务Apache/Nginx/PHP-FPMLinux 环境编译 PHP 时添加--with-gd参数或通过包管理器安装php-gd扩展如yum install php-gd/apt install php-gd重启服务生效生成验证码第一步开启Session与配置?php// 开启Session用于存储验证码校验值必须在输出前执行无任何前置空格session_start();// 引入验证码配置$captchaConfig[// 基础尺寸配置width150,// 验证码图片宽度height50,// 验证码图片高度// 字符配置length4,// 验证码字符长度常用4-6位charset23456789ABCDEFGHJKLMNPQRSTUVWXYZ,// 字符集去掉易混淆的0/O、1/l提升用户体验font_size24,// 字体字号font_file./fonts/arial.ttf,// TTF字体文件路径必须填写正确否则无法绘制文字// 干扰项配置平衡安全性与识别度line_num6,// 干扰线数量pixel_num100,// 噪点数量// 安全配置expire300,// 验证码有效期单位秒默认5分钟session_keycaptcha_code,// Session存储的key];第二步创建画布分配基础颜色// 创建真彩色画布$imgimagecreatetruecolor($captchaConfig[width],$captchaConfig[height]);// 分配背景色浅色系背景提升文字辨识度240-255区间$bgColorimagecolorallocate($img,245,245,245);// 分配文字颜色深色系随机生成避免固定色值被OCR识别$textColorimagecolorallocate($img,rand(10,50),rand(10,50),rand(10,50));// 填充画布背景imagefill($img,0,0,$bgColor);API 函数核心作用imagecreatetruecolor(int $width, int $height)创建真彩色图像画布是验证码的载体imagecolorallocate(resource $image, int $red, int $green, int $blue)为画布分配 RGB 颜色用于背景、文字、干扰项绘制imagefill(resource $image, int $x, int $y, int $color)为画布填充背景色从坐标 (x,y) 开始填充第三步生成随机验证码字符串$code;$charsetLenstrlen($captchaConfig[charset]);for($i0;$i$captchaConfig[length];$i){// 从字符集中随机取一个字符拼接成最终验证码$code.$captchaConfig[charset][rand(0,$charsetLen-1)];}第四步绘制干扰元素先画干扰项再画文字避免文字被遮挡// 绘制随机干扰线for($i0;$i$captchaConfig[line_num];$i){// 随机生成线条颜色浅色系不抢文字视觉$lineColorimagecolorallocate($img,rand(100,200),rand(100,200),rand(100,200));// 随机生成线条起点和终点贯穿整个画布imageline($img,rand(0,$captchaConfig[width]),rand(0,$captchaConfig[height]),rand(0,$captchaConfig[width]),rand(0,$captchaConfig[height]),$lineColor);}// 绘制随机噪点for($i0;$i$captchaConfig[pixel_num];$i){// 随机生成噪点颜色$pixelColorimagecolorallocate($img,rand(50,150),rand(50,150),rand(50,150));// 随机生成噪点位置imagesetpixel($img,rand(0,$captchaConfig[width]),rand(0,$captchaConfig[height]),$pixelColor);}imageline(resource $image, int $x1, int $y1, int $x2, int $y2, int $color)绘制直线多用于添加干扰线增加机器自动识别难度imagesetpixel(resource $image, int $x, int $y, int $color)绘制单个像素点用来生成噪点干扰强化验证码防破解效果第五步绘制验证码字符到画布// 计算单个字符的宽度均匀分布在画布上$singleWidth$captchaConfig[width]/$captchaConfig[length];for($i0;$i$captchaConfig[length];$i){// 每个字符随机旋转-10到10度防止机器识别$anglerand(-10,10);// 计算字符的x坐标左右留边距均匀分布$x$singleWidth*$irand(5,10);// 计算字符的y坐标垂直居中基线对齐避免文字下沉$y$captchaConfig[height]/2$captchaConfig[font_size]/3;// 写入单个字符到画布imagettftext($img,$captchaConfig[font_size],$angle,$x,$y,$textColor,$captchaConfig[font_file],$code[$i]);}imagettftext(resource $image, float $size, float $angle, int $x, int $y, int $color, string $font_file, string $text)写入 TrueType 字体文本是绘制验证码字符的核心支持自定义字体、字号、文字旋转角度第六步存储验证码到Session完成服务端持久化// 存储加密后的验证码过期时间生产环境建议加密存储避免Session泄露$_SESSION[$captchaConfig[session_key]][codestrtolower($code),// 转小写实现不区分大小写校验提升用户体验expire_timetime()$captchaConfig[expire]// 过期时间戳];第七步输出图片到浏览器// 声明响应头为PNG图片禁止浏览器缓存header(Content-Type: image/png);header(Cache-Control: no-cache, no-store, must-revalidate);header(Pragma: no-cache);// 输出图片imagepng($img);// 销毁画布资源释放内存imagedestroy($img);imagepng(resource $image)以 PNG 格式输出图像可直接推送到浏览器也能保存为图片文件imagedestroy(resource $image)销毁画布图像资源释放服务器内存是代码收尾必备操作header(string $header)设置 HTTP 响应头告知浏览器返回内容为图片格式避免页面出现乱码校验验证码?php// 1. 开启Session与生成端保持一致session_start();// 2. 配置项必须与生成端保持一致$captchaConfig[session_keycaptcha_code,];// 3. 封装校验函数可全局复用functioncheckCaptcha(string$userInput):array{global$captchaConfig;// 3.1 先判断用户是否输入了验证码if(empty($userInput)){return[statusfalse,msg请输入验证码];}// 3.2 判断服务端是否存在验证码Sessionif(!isset($_SESSION[$captchaConfig[session_key]])){return[statusfalse,msg验证码已过期请刷新重试];}// 3.3 取出Session中的验证码数据$captchaData$_SESSION[$captchaConfig[session_key]];// 3.4 校验验证码是否过期if(time()$captchaData[expire_time]){// 过期后立即销毁防止复用unset($_SESSION[$captchaConfig[session_key]]);return[statusfalse,msg验证码已过期请刷新重试];}// 3.5 校验验证码是否正确统一转小写不区分大小写if(strtolower(trim($userInput))!$captchaData[code]){// 校验失败立即销毁防止暴力破解unset($_SESSION[$captchaConfig[session_key]]);return[statusfalse,msg验证码错误请刷新重试];}// 3.6 校验成功立即销毁当前验证码防止重放攻击单次有效unset($_SESSION[$captchaConfig[session_key]]);return[statustrue,msg验证码校验通过];}// 4. 调用示例用户POST提交表单时if($_SERVER[REQUEST_METHOD]POST){// 获取用户输入的验证码$userCaptcha$_POST[captcha]??;// 执行校验$checkResultcheckCaptcha($userCaptcha);if(!$checkResult[status]){// 校验失败返回错误信息echojson_encode([code400,msg$checkResult[msg]]);exit;}// 校验通过执行后续业务逻辑登录、注册、发送短信等echojson_encode([code200,msg操作成功]);exit;}生产环境注意事项与安全规范必须使用 HTTPS 传输验证码接口和表单提交接口必须通过 HTTPS 传输防止中间人窃取验证码图片和提交内容规避重放攻击。验证码存储安全生产环境严禁将验证码原始字符串返回给前端必须仅存储在服务端 Session/Redis 中高并发场景建议使用 Redis 存储验证码替代原生 Session提升性能和分布式系统兼容性建议对存储的验证码进行不可逆加密避免 Session/Redis 泄露导致验证码被破解。用户体验与安全平衡字符集必须剔除易混淆的0和O、1和l、2和Z等字符减少用户输入错误干扰线和噪点数量需合理避免过度干扰导致用户无法识别必须实现不区分大小写校验降低用户输入门槛。防暴力破解规范验证码必须单次有效无论校验成功或失败立即销毁禁止重复使用同一 IP 短时间内多次获取验证码需进行频率限制防止验证码被批量抓取校验失败 3 次以上必须强制刷新验证码避免暴力枚举。字体与资源规范必须使用开源免费字体避免商用字体导致的版权风险建议使用多种字体随机切换每个字符使用不同字体大幅提升 OCR 识别难度字体文件路径建议使用绝对路径避免相对路径导致的绘制失败。输出规范必须设置禁止缓存的响应头防止浏览器、CDN 缓存验证码图片导致校验失败输出图片前必须清空输出缓冲区避免框架输出的多余内容导致图片乱码图片输出后必须执行imagedestroy()销毁画布资源避免服务器内存泄漏。严禁存储敏感信息验证码仅用于人机校验禁止在其中嵌入用户 ID、密码等敏感信息。

更多文章