captchabuilder->getphrase()只能调用一次,必须在build()后立即存入session,否则答案丢失;多worker需改用redis session驱动。

Webman 中 CaptchaBuilder->getPhrase() 只能调一次,不立刻存 session 就丢答案
这是 Webman 验证码最常踩的坑:生成后没马上取值存 session,校验时 getPhrase() 返回空字符串,导致“输对也报错”。CaptchaBuilder 内部用一次性 salt 生成 phrase,调完就清空,不是 session 没生效,是对象本身设计如此。
-
$builder->build()后必须紧跟着$request->session()->set('captcha', strtolower($builder->getPhrase())) - 绝不能在登录校验逻辑里再调
getPhrase()—— 此时已为空 - 如果用了多 worker(如 reload 模式),
file驱动的 session 会因进程隔离失效,必须切到redis驱动
接口返回乱码或空白图片?检查响应体是否被污染
/login/captcha 返回的不是 HTML,而是二进制 PNG 流。GD 库极度敏感,任何额外输出(哪怕一个空格、warning 或 echo)都会破坏图像头,浏览器解析失败,表现为乱码、下载弹窗或空白。
- 控制器方法里禁止
echo/var_dump/print_r等调试输出 - 关掉 PHP 错误显示:
ini_set('display_errors', 'Off') - 强制指定 header:
['Content-Type' => 'image/png'](别用jpeg,GD 默认可能输出png,格式错配部分浏览器直接拒渲染) - 用 curl 验证原始响应:
curl -v http://127.0.0.1:8787/login/captcha | head -c 10,开头应为‰PNG
刷新验证码后旧值还能通过?说明没及时 delete session key
Webman 的 CaptchaBuilder 不自带自动失效机制。“刷新”只是生成新图,但旧 session 值还在,用户输旧码仍能比对成功 —— 这不是 bug,是设计遗漏,必须手动补上生命周期管理。
Webman 2.2.0版本强化了 TCP/UDP 服务支持,优化路由组管理,并增强异步任务处理能力。结合协程与连接池技术,Webman 能轻松应对高并发场景,适用于网站、接口服务、即时通讯、物联网及游戏开发,兼具高性能、灵活扩展与稳定可靠,是多场景 PHP 服务开发的理想选择。
- 刷新接口(如
GET /login/captcha/refresh)中,先执行$request->session()->delete('captcha') - 再
$builder->build(),立刻set新值,顺序不能颠倒 - 若页面含多个表单(如登录+注册共存),别复用固定 key
'captcha',改用带随机后缀的 key,例如'captcha_'.uniqid() - 校验成功后,**立即**
$request->session()->delete('captcha'),防止重放
多 worker 下 session 取不到值?确认驱动是否统一且可跨进程共享
Webman 默认基于 PHP 内置 session,但在 CLI 或多进程 reload 模式下,session_start() 无法跨 worker 共享。file 驱动天然隔离,Redis 驱动才是生产环境唯一靠谱选择。
- 配置
config/session.php中'handler' => 'redis',并确保 Redis 连接正常 - 避免混用 driver:不要一部分请求走 file,一部分走 redis
- 检查
session_name()是否一致,不同 name 会导致 key 隔离 - 上线前用并发请求验证:两个 worker 同时访问
/login/captcha和/login/check,看 session 值能否正确传递
真正难的不是生成那张图,而是让 session 的写、读、删在任意 worker、任意时间点都严格对齐——漏掉任何一个环节,验证码就从防护变成摆设。










