PHP 分布式验证码登录解决方案

✨ 传统验证码登录方案

传统方案的核心是session上下文,整个流程高度依赖后端渲染页面。

生成流程
  • 前端发起验证码请求。
  • 后端生成验证码图片,并将验证码文本存储在session中。
  • 返回验证码图片给前端显示。
验证流程
  • 用户输入用户名、密码和验证码。
  • 后端从session中取出验证码文本进行比对。
  • 验证通过后,后端跳转页面。

这种方案适合单体应用,但前后端分离后,session跨域问题和页面跳转逻辑会变得棘手。

🐛 前后端分离的分布式解决方案

在分布式环境中,我们引入Redis存储验证码(取代session),并生成唯一标识符(key)来关联请求。同时,登录成功后返回token,前端负责页面跳转。

生成流程
  • 前端请求验证码。
  • 后端生成验证码图片和文本,将文本与唯一key关联存储到Redis。
  • 返回Base64编码的图片和key给前端。

对比传统方案,增加了Redis和key机制,确保分布式一致性。

验证流程
  • 用户输入用户名、密码、验证码和key。
  • 后端从Redis中根据key取出验证码文本进行验证。
  • 验证通过,返回token;失败则提示错误。
  • 前端根据token处理后续逻辑(如跳转)。

这一方案解耦了前后端,适用于微服务和云部署环境。

👻 项目案例

为了让大家上手更轻松,我以webman框架为例,集成我的开源插件tinywan/captcha。该插件专为webman设计,

安装插件

在webman项目根目录执行:

代码语言:javascript

代码运行次数:0

运行

AI代码解释

复制代码
composer require tinywan/captcha

安装后,Composer会自动加载依赖。确保你的PHP环境支持GD或Imagick扩展(用于图片生成)。

生成验证码

插件使用Captcha::base64()方法生成Base64编码的验证码,直接嵌入HTML标签。

示例控制器代码(IndexController.php):

代码语言:javascript

代码运行次数:0

运行

AI代码解释

复制代码
<?php
/**
 * @desc IndexController
 * @author Tinywan(ShaoBo Wan)
 */
declare(strict_types=1);

namespaceapp\home\v1\controller;

usesupport\Request;
usesupport\Response;

class IndexController
{
    /**
     * @desc: 图片验证码
     * @param Request $request
     * @return Response
     * @throws \Exception
     * @author Tinywan(ShaoBo Wan)
     */
    publicfunction captcha(Request $request): Response
    {
        $captcha = \Tinywan\Captcha\Captcha::base64();
        return json($captcha);
    }
}

访问http://127.0.0.1:8288/home/v1/index/captcha,响应示例:

代码语言:javascript

代码运行次数:0

运行

AI代码解释

复制代码
{
  "key": "$2y$10$3bSPqTNT33WdwOQnG7TXQOfqlTBJKhv5AwcDFrQZQxuGKVArJcszy",
  "base64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPoAAAA+BAMAAADwuxusAAAAG1BMVEXz+/5NND7e4uaLfoa0sLZhTFbJyc6gl552ZW6wM8bHAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACjUlEQVRYhe1Xz2/TMBgtzq8eeWyFHROJDY4rIMEx2ei4LkNDPbZoII4N07QdG2kT/NmznXrMnyvFcYJ28TtVX/35+fv17IxGHh4eHh4eFBdPSf4LufVadvDlw6DkMXBqufLyDsCkJ99Pyv7Kzq+ARD/yK5Lp2jacIdh/AIeaYQmsrDyXgnveq+480VhrljHwwso1A07SPtyj0T5wq2/Bz7Njrouvj6jpGeBKrvwq7NK/plt2DUvgHbFFwMKNPFDh1WK+dLKMdgKPnJNjjxh5iXI39gLfmh8ldi5LPazALHwlu5tw8XUrdnGddiZnUI09lftOUv1PEmbSzNbasJ7DzFM7xg+Myy0bV7SgESZ5CDzXNwkbV0tl1PdH026bsF7qZPI0N6kyJDgTWSLssSM7a/xWzUEm74m4JvI0s0cJOU5FqxCeZpd53pWdB7c72wTPPqc8/fqEl7zwM5IQHjvl4cLgIjc88Yes/jfWSzL0XMGvVGkUeJ5PyDYlOZ8dYnkvRg96zqdZH7GoGYT8kYmJ4SCXX20qlQX2ZVID1elvajo2oUEuVoNeP1Pbu5h4CfaxatepKey1wRSao8ELuOVCaEPYRFGoiKfmlcpV4DcxlX+OqQoVhvhaIJN5/QSlKYVxf/C8GKYD2YypfkaHZ1WNDTYnjxfGEkYjl4iI1GcODxuuJXtvt+m2jafG7nLB8xOficfb+W1Xz4Dof+TAXooIMpd2zQhb/NF477QhkfOVObTr69LlyAb7qWjXruw3fyFK1heVKF53oZBDkvZmj8ULvLtEC42we+e3g94r7ajxdTEQOev+JGHfB+KWUr8ebLPOCGy/1f4LEufPkEFQ9fzs7od4/pTsHh4eHh4efXEP4hlXg7Y3KSYAAAAASUVORK5CYII="
}
  • key:唯一标识,用于后续验证。
  • base64:图片数据,可直接用于<img src="...">

预览图片:复制base64到浏览器或在线工具查看。

示例验证码图片:

或者浏览器直接输出

截图

验证验证码

在登录接口中使用Captcha::check()验证:

代码语言:javascript

代码运行次数:0

运行

AI代码解释

复制代码
use Tinywan\Captcha\Captcha;

$code = $request->get('code'); // 用户输入的验证码
$key = $request->get('key');   // 之前生成的验证码 key
if (false === Captcha::check($code, $key)) {
    // 验证失败
    return '验证码错误';
}
// 验证通过,返回token或其他逻辑
return '验证码正确';

验证通过后,可生成JWT token返回给前端,实现无状态认证。

📦 小结

这个分布式验证码登录方案的优势显而易见:

  • 高可用性:Redis确保验证码在分布式节点间一致。
  • 安全性:Base64避免文件存储风险,key机制防止伪造。
  • 高效集成 :webman的协程特性让生成/验证极速。
相关推荐
BingoGo2 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack2 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
BingoGo3 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack3 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack3 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo3 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
初次攀爬者4 天前
ZooKeeper 实现分布式锁的两种方式
分布式·后端·zookeeper
JaguarJack5 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理5 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
feifeigo1235 天前
matlab画图工具
开发语言·matlab