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的协程特性让生成/验证极速。
相关推荐
C++ 老炮儿的技术栈2 分钟前
什么是通信规约
开发语言·数据结构·c++·windows·算法·安全·链表
@大迁世界5 分钟前
TypeScript 的本质并非类型,而是信任
开发语言·前端·javascript·typescript·ecmascript
栗子叶11 分钟前
Java对象创建的过程
java·开发语言·jvm
Amumu1213819 分钟前
React面向组件编程
开发语言·前端·javascript
IT=>小脑虎20 分钟前
Python零基础衔接进阶知识点【详解版】
开发语言·人工智能·python
wjs202423 分钟前
C 标准库 - `<float.h>》详解
开发语言
zfj32130 分钟前
CyclicBarrier、CountDownLatch、Semaphore 各自的作用和用法区别
java·开发语言·countdownlatch·semaphore·cyclicbarrier
张np37 分钟前
java基础-ConcurrentHashMap
java·开发语言
早日退休!!!38 分钟前
进程与线程的上下文加载_保存及内存映射
开发语言
jllllyuz39 分钟前
MATLAB实现蜻蜓优化算法
开发语言·算法·matlab