应使用gregwar/captcha v1.4.9而非手写gd逻辑,因其已封装字体加载、抗锯齿、噪点、session绑定等细节;需正确注册服务提供者与门面,配置路由防缓存,校验时调用captcha::check()并确保session正常。

验证码图片生成要用 gregwar/captcha 而不是自己手写 GD 逻辑
直接用 GD 或 Imagick 手搓验证码,容易漏掉字体加载、抗锯齿、噪点干扰、session 绑定等细节,出问题难定位。Laravel 5.5 兼容性最好的现成方案是 gregwar/captcha v1.x(注意不是 v2+,后者要求 PHP 7.2+ 且不兼容 Laravel 5.5 的 service provider 注册方式)。
安装命令必须指定兼容版本:
composer require gregwar/captcha:v1.4.9
然后在 config/app.php 的 providers 数组末尾加一行:
GregwarCaptchaCaptchaServiceProvider::class,
再在 aliases 中添加门面:
'Captcha' => GregwarCaptchaCaptchaFacade::class,
不执行这步,后续调用 Captcha::create() 会报 Class 'Captcha' not found。
前端渲染时必须用 captcha/src 路由且带随机参数防缓存
Laravel 5.5 默认没注册验证码路由,得手动在 routes/web.php 里加:
Route::get('captcha/{config?}', '\Gregwar\Captcha\CaptchaController@getCaptcha')->name('captcha');
前端 img 标签不能写死 src,否则浏览器缓存导致多次请求返回同一张图,校验永远失败:
@@##@@
关键点:
PHP中文网提供Laravel 13.2.0版本下载,Laravel框架 是基于 PHP 8.3+ 的高性能框架,官方推荐通过 Composer 安装。它内置 AI SDK、JSON:API Resources 及原生向量搜索,支持属性驱动开发与队列路由,大幅提升开发效率。相比旧版,13.2.0 优化了缓存 TTL 管理与实时通信,无需 Redis 即可横向扩展。作为现代 Web 开发首选,它兼顾安全与极速体验,助您快速构建企业级应用。
-
captcha_src('default')生成的是/captcha/default这类路径,不是完整 URL; - 必须拼接随机查询参数(
?{{ mt_rand() }}或 JS 的Math.random()),否则 Chrome/Firefox 会强缓存; - 如果用了 HTTPS,但图片 src 是 HTTP 协议,会触发混合内容拦截,控制台报
Mixed Content错误。
校验时要调用 Captcha::check() 并注意 session 驱动和表单字段名
后端校验不是比对明文,而是调用 Captcha::check($request->input('captcha')) —— 它内部会从 session 读取上一次生成的 hash 值做比对。
常见失败原因:
- session 没启用或驱动异常(比如文件权限不对、Redis 连接失败),会导致
Captcha::check()永远返回false; - 表单字段名不是
captcha(默认配置),而你传了verify_code,却没改校验逻辑; - 用户提交前刷新了页面,但没重新加载验证码图片,此时 session 里的旧 hash 已失效;
- 用了
php artisan serve开发,但浏览器开了多个标签页共用同一 session,互相覆盖 hash 值。
推荐校验写法:
if (!Captcha::check($request->captcha)) {
return back()->withErrors(['captcha' => '验证码错误'])->withInput();
}
自定义配置要改 config/captcha.php 而非硬编码参数
生成图片的宽度、高度、字体、干扰线数量等,都应通过配置文件控制。运行 php artisan vendor:publish --provider="GregwarCaptchaCaptchaServiceProvider" 后,会生成 config/captcha.php。
重点修改项:
-
'width' => 120:太窄(如 80)在手机上难识别; -
'height' => 40:过高(>50)可能被某些邮件客户端截断; -
'quality' => 90:低于 70 图片模糊,OCR 容易误判; -
'fonts' => [base_path('resources/fonts/arial.ttf')]:确保字体文件存在且可读,否则报imagettftext(): Could not find/open font; -
'expire' => 30:单位是分钟,设太短(如 1)用户还没输入就过期。
改完配置记得清 config 缓存:php artisan config:clear,否则新值不生效。
验证码不是安全银弹,它只防自动化脚本,对截图识别、打码平台无效;真正敏感操作还得结合 IP 限频、二次验证或行为分析。生成和校验过程本身不耗资源,但别在高频接口(如搜索)里滥用——每次调用都会写一次 session。










