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的协程特性让生成/验证极速。
相关推荐
无语......7 分钟前
安装uv并管理 Python / 包
开发语言·python·uv
道剑剑非道9 分钟前
【C++ 仿 MFC 反射系统】
开发语言·c++·mfc
我要用代码向我喜欢的女孩表白34 分钟前
在spark集群上在部署一套spark环境,不要影响过去环境
大数据·分布式·spark
Elastic 中国社区官方博客41 分钟前
在 Elastic 中使用 OpenTelemetry 内容包可视化 OpenTelemetry 数据
大数据·开发语言·数据库·elasticsearch·搜索引擎
C+++Python43 分钟前
如何学习Python的应用领域知识?
开发语言·python·学习
wuyoula1 小时前
图片版ping接口源码
php·php源码
疯狂打码的少年1 小时前
【Day12 Java转Python】Python工程的“骨架”——模块、包与__name__
java·开发语言·python
全栈开发圈1 小时前
新书速览|MATLAB数据分析与可视化实践:视频教学版
开发语言·matlab·数据分析
网域小星球1 小时前
C 语言从 0 入门(二十二)|内存四区:栈、堆、全局、常量区深度解析
c语言·开发语言
晓纪同学1 小时前
EffctiveC++_第三章_资源管理
开发语言·c++·算法