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的协程特性让生成/验证极速。
相关推荐
Lethehong5 分钟前
【探索实战】Kurator分布式云原生平台快速上手与实战指南
分布式·云原生
快乐非自愿6 分钟前
Java函数式接口——渐进式学习
java·开发语言·学习
爱吃大芒果7 分钟前
Flutter 表单开发实战:表单验证、输入格式化与提交处理
开发语言·javascript·flutter·华为·harmonyos
福尔摩斯张8 分钟前
TCP/IP网络编程深度解析:从Socket基础到高性能服务器构建(超详细)
linux·运维·服务器·开发语言·网络·网络协议·tcp/ip
superman超哥12 分钟前
仓颉语言中网络套接字封装的深度剖析与工程实践
c语言·开发语言·c++·python·仓颉
wanghowie13 分钟前
01.01 Java基础篇|语言基础与开发环境速成
java·开发语言
白露与泡影15 分钟前
2026年Java面试题目收集整理归纳(持续更新)
java·开发语言·面试
画江湖Test34 分钟前
分布式缓存穿透解决方案
分布式·缓存·电商系统·缓存解决方案
辞旧 lekkk35 分钟前
【c++】c++11(上)
开发语言·c++·学习·萌新
程序员阿鹏36 分钟前
SpringBoot自动装配原理
java·开发语言·spring boot·后端·spring·tomcat·maven