ThinkPHP5验证码安全关键在干扰设计与Session校验:干扰线宜3–6条低对比随机绘制,噪点20–40个同色略浅,禁用useNoise、优化useCurve参数,字体需动态加载,Session校验必须唯一键+即时销毁。

ThinkPHP5 验证码的图像识别难度,不取决于“有没有干扰线或噪点”,而在于干扰的类型、密度、颜色对比度与字符结构的耦合关系。实测表明:盲目堆砌干扰反而提升 OCR 准确率,尤其对现代 CNN+CTC 模型而言。
干扰线不是越多越安全
规律性干扰(如等距横线、固定角度斜线、网格状线条)会成为 OCR 定位字符行和切分单字的强锚点。模型能轻易拟合这些线性结构,并反向推导文字基线位置。
- 推荐数量:3–6 条,用
imageline()随机起止点绘制 - 颜色控制:背景若为 rgb(240,240,240),干扰线建议 rgb(190,190,190) —— 略深但低对比,避免形成边缘突变
- 避开高频区:不要让干扰线穿过字符中部或紧贴笔画边缘,否则易被识别为“字符粘连”特征而强化分割信心
噪点设计不当等于帮攻击者预处理
随机像素点若颜色过深、坐标集中、或与文字色反差大,会人为制造高对比噪点簇,CNN 模型可将其识别为“字符轮廓强化点”,反而提升识别置信度。
- 建议数量:20–40 个,用
imagesetpixel()绘制 - 颜色策略:与验证码文字同色,或略浅 10–20 单位(如文字 rgb(50,50,50),噪点用 rgb(80,80,80))
- 绝对禁止:在文字正上方/内部密集打点 —— 这会造成字符断裂,人眼难读,但模型极擅长基于断裂点做单字切分
字体与扭曲比干扰线更关键
ThinkPHP5 内置 useCurve => true 仅叠加一条固定贝塞尔曲线,路径僵硬、粗细恒定,在高 DPI 下易断裂或糊成黑块;useNoise => true 在 fontSize < 20 或 length > 4 时极易污染字符主体。
立即学习“PHP免费学习笔记(深入)”;
- 真实有效组合:关闭
useNoise,开启useCurve,同时将imageH ≥ 50、fontSize ≥ 22 - 旋转角度务必限制在 ±12° 内:超出后 Tesseract 和 EasyOCR 均出现定位偏移下降,但主流商用 API(如百度 OCR、腾讯云)反而因训练数据覆盖广而识别更稳
- 字体层面防识别需侵入式改造:GD 驱动不支持配置切换,必须继承重写
generate(),动态加载不同 .ttf 文件(如 simhei.ttf / msyhbd.ttf / arial.ttf)
Session 校验逻辑是最大短板
所有图像增强都挡不住一次成功的 Session 劫持或重放。ThinkPHP5 的 captcha_check() 默认只校验 think_captcha 键,且不自动失效。攻击者只要抓包一次有效 session_id + 验证码值,即可无限重放。
- 生成后立即存入唯一键:如
$_SESSION['captcha_'.uniqid()] = strtolower($code) - 校验时严格比对并即时销毁:
if (isset($_SESSION[$key]) && $_SESSION[$key] === $input) { unset($_SESSION[$key]); return true; } - 禁用
use_trans_sid,防止 session_id 泄露到 URL 中



















