🔥 超强实战!基于 Webman + Redis 的分布式验证码登录方案,一文搞定高并发验证!
🚀 引言:为什么传统的验证码登录已经不够用了?
在传统的单体 Web 应用中,我们通常使用 Session 来存储验证码信息,用户登录时直接从 Session 中取出验证码进行比对。这种方式简单直接,但在分布式、微服务架构下,Session 无法跨节点共享,导致验证码状态不一致,登录失败率高,扩展性差。
随着前后端分离成为主流,越来越多的项目采用 Vue、React 等框架构建前端,后端则提供纯 API 服务。在这种架构下,Session 机制显得力不从心,我们需要一种更高效、可扩展的验证码登录方案。
今天,我将结合 Webman 框架 和开源插件 tinywan/captcha,带你从零实现一个高性能、分布式友好的验证码登录系统,支持高并发、跨域访问,并完整集成 Redis 作为状态存储。
🧩 一、架构设计:分布式验证码登录的核心思路
在分布式环境中,我们不再依赖 Session,而是引入 Redis 作为验证码存储中间件,并通过唯一 Key 关联每次验证码请求。整体流程分为两部分:
✅ 生成验证码流程:
- 前端请求验证码接口;
- 后端生成验证码图片和文本,将文本与 Key 存入 Redis(设置过期时间);
- 返回 Base64 格式的图片和 Key 给前端。
✅ 验证验证码流程:
- 用户提交登录信息(用户名、密码、验证码、Key);
- 后端根据 Key 从 Redis 中取出验证码文本进行比对;
- 验证通过后生成 Token 返回,前端跳转至首页。
🛠️ 二、技术选型:为什么选择 Webman + tinywan/captcha?
- Webman:基于 Workerman 的高性能 PHP 框架,支持协程、常驻内存,非常适合高并发 API 场景。
- tinywan/captcha:轻量级验证码插件,支持 Base64 输出,无需文件 I/O,天生适合分布式环境。
📦 三、实战开始:集成验证码插件
步骤1:安装插件
在 Webman 项目根目录执行:
composer require tinywan/captcha
确保你的 PHP 已安装 GD 或 Imagick 扩展。
步骤2:编写验证码生成接口
在控制器中编写生成验证码的方法:
<?php
namespace app\controller;
use support\Request;
use support\Response;
use Tinywan\Captcha\Captcha;
class LoginController
{
public function captcha(Request $request): Response
{
$captcha = Captcha::base64();
return json([
'key' => $captcha['key'],
'base64' => $captcha['base64']
]);
}
}
访问该接口会返回如下结构:
{
"key": "$2y$10$3bSPqTNT33WdwOQnG7TXQOfqlTBJKhv5AwcDFrQZQxuGKVArJcszy",
"base64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPoAAAA+BAMAAADwuxusAAAAG1BMVEXz+/5NND7e4uaLfoa0sLZhTFbJyc6gl552ZW6wM8bHAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACjUlEQVRYhe1Xz2/TMBgtzq8eeWyFHROJDY4rIMEx2ei4LkNDPbZoII4N07QdG2kT/NmznXrMnyvFcYJ28TtVX/35+fv17IxGHh4eHh4eFBdPSf4LufVadvDlw6DkMXBqufLyDsCkJ99Pyv7Kzq+ARD/yK5Lp2jacIdh/AIeaYQmsrDyXgnveq+480VhrljHwwso1A07SPtyj0T5wq2/Bz7Njrouvj6jpGeBKrvwq7NK/plt2DUvgHbFFwMKNPFDh1WK+dLKMdwKPnJNjjxh5iXI39gLfmh8ldi5LPazALHwlu5tw8XUrdnGddiZnUI09lftOUv1PEmbSzNbasJ7DzFM7xg+Myy0bV7SgESZ5CDzXNwkbV0tl1PdH026bsF7qZPI0N6kyJDgTWSLssSM7a/xWzUEm74m4JvI0s0cJOU5FqxCeZpd53pWdB7c72wTPPqc8/fqEl7zwM5IQHjvl4cLgIjc88Yes/jfWSzL0XMGvVGkUeJ5PyDYlOZ8dYnkvRg96zqdZH7GoGYT8kYmJ4SCXX20qlQX2ZVID1elvajo2oUEuVoNeP1Pbu5h4CfaxatepKey1wRSao8ELuOVCaEPYRFGoiKfmlcpV4DcxlX+OqQoVhvhaIJN5/QSlKYVxf/C8GKYD2YypfkaHZ1WNDTYnjxfGEkYjl4iI1GcODxuuJXtvt+m2jafG7nLB8xOficfb+W1Xz4Dof+TAXooIMpd2zQhb/NF477QhkfOVObTr69LlyAb7qWjXruw3fyFK1heVKF53oZBDkvZmj8ULvLtEC42we+e3g94r7ajxdTEQOev+JGHfB+KWUr8ebLPOCGy/1f4LEufPkEFQ9fzs7od4/pTsHh4eHh4efXEP4hlXg7Y3KSYAAAAASUVORK5CYII="
}
前端可直接将 base64
用于 <img>
标签的 src
属性。
步骤3:验证验证码
在登录接口中验证用户输入的验证码:
public function login(Request $request): Response
{
$code = $request->post('code');
$key = $request->post('key');
if (false === Captcha::check($code, $key)) {
return json(['code' => 400, 'msg' => '验证码错误']);
}
// 验证通过,继续验证账号密码...
// 生成 JWT Token 返回
$token = $this->generateToken($user);
return json(['code' => 200, 'token' => $token]);
}
🧠 四、深入原理:插件是如何工作的?
生成阶段:
插件使用 GD/Imagick 生成图片,并将验证码文本与 Key 关联存入 Redis(默认有效期 5 分钟)。验证阶段:
根据 Key 从 Redis 中取出验证码文本,比对后立即删除 Key,防止重复使用。
🧪 五、扩展建议:如何进一步提升安全性?
- 限制验证码尝试次数:在 Redis 中记录每个 IP 或 Key 的错误次数,超过则锁定。
- 使用图形干扰:插件内置了干扰线、扭曲变形等机制,可配置复杂度。
- 启用 HTTPS:防止验证码在传输过程中被截获。
- 定时清理 Redis:可设置定时任务清理过期验证码记录。
✅ 六、总结
我们通过 Webman + tinywan/captcha + Redis 实现了一个完全分布式友好的验证码登录方案,具备以下优势:
- 🚀 高性能:Webman 协程架构支持高并发;
- 🧩 解耦前后端:纯 API 设计,适合 Vue/React 任何前端框架;
- 🔒 安全可靠:Redis 存储 + Key 机制,防止伪造和重放;
- 📦 开箱即用:插件封装完善,集成简单。
如果你正在构建一个分布式系统,或正在重构传统项目,这个方案一定值得你尝试!
📚 资源链接
- Webman 官网:https://www.workerman.net/webman
- tinywan/captcha 插件:https://www.workerman.net/plugin/33