基于 Redis 实现验证码登录

基于 Redis 实现验证码登录

一、我的理解

  • 基于 Session 实现验证码登录,集群环境下,多个 Tomcat 服务器 Session 共享。
  • 基于 Redis 实现验证码登录,实现集群环境下,更新用户登录信息。

二、操作步骤














三、AI 的理解

你的理解是正确的。你准确地抓住了两种方案的核心目的:

  1. 基于 Session 的方案:其核心挑战与解决方案都围绕着如何让多个 Tomcat 服务器共享 Session 数据,以解决集群环境下的登录状态不一致问题。
  2. 基于 Redis 的方案:这是一种更现代和主流的 Token 架构,它利用 Redis 作为集中式存储来保存用户的登录信息(如用户ID、昵称等),并通过拦截器在每次请求时验证和更新(刷新)登录信息的有效期。

下面我将为你详细解析这两种方案的实现原理和区别。

🧩 方案一:基于 Session 的验证码登录与集群共享

这种方案是传统 Web 应用登录方式的延伸,核心在于将原本存储在单个 Tomcat 内存中的 Session 数据,迁移到一个所有 Tomcat 都能访问的"中央仓库"中。

单机环境下的流程

在未部署集群时,流程非常简单:

  1. 用户请求获取验证码,服务器生成验证码后,使用 session.setAttribute("code", code) 将其存入当前 Tomcat 的内存中。
  2. 用户提交手机号和验证码进行登录,服务器从 session.getAttribute("code") 取出验证码进行比对。
  3. 校验通过后,将用户信息也存入 Session,标记为登录状态。
集群环境下的问题

当部署了多个 Tomcat 服务器并由 Nginx 进行负载均衡时,问题就出现了:

  • 第一次请求 :用户被分配到 Tomcat-1,验证码存入了 Tomcat-1 的内存。
  • 第二次请求 :用户的登录请求被 Nginx 分发到了 Tomcat-2。由于 Tomcat-2 的内存中没有之前保存的验证码,导致校验失败。

这就是所谓的 Session 粘滞性问题

解决方案:Redis 实现 Session 共享

业界最主流的解决方案就是使用 Redis 作为集中的 Session 存储器

  • 改造点 :将所有 session.setAttribute()session.getAttribute() 的操作,替换为对 Redis 的读写操作。
  • 效果:无论用户的请求被分发到哪一台 Tomcat,它们都去同一个 Redis 服务器存取验证码和用户 Session 信息,从而实现了 Session 的共享。

✨ 方案二:基于 Redis 的 Token 登录与信息更新

这是一种更彻底的改造,它完全抛弃了传统的 Servlet Session 机制,采用了无状态的 Token 架构。这也是目前微服务和前后端分离项目中最常用的方式。

核心流程
  1. 登录认证

    • 用户提交手机号和验证码。
    • 服务端从 Redis 中校验验证码(Key 为手机号)。
    • 校验通过后,根据手机号查询或创建用户。
    • 服务端生成一个全局唯一的随机字符串作为 Token (例如使用 UUID)。
    • 将用户信息(如 ID、昵称等)转换为一个 Map,并以 Hash 结构存入 Redis,Key 为这个 Token(例如 login:token:{token}),同时设置一个过期时间(如 30 分钟)。
    • 将这个 Token 返回给前端(通常放在响应体或 Cookie 中)。
  2. 后续请求与登录信息更新

    • 前端在之后的每一次请求中,都在请求头(如 Authorization)携带这个 Token。
    • 服务端通过一个 拦截器 (Interceptor) 拦截所有需要登录的请求。
    • 拦截器从请求头中获取 Token,然后去 Redis 中查询对应的用户信息。
    • 如果查不到,说明未登录或登录已过期,直接返回 401 状态码。
    • 如果能查到,则将用户信息保存到 ThreadLocal 中,供本次请求的后续业务逻辑使用。
    • 关键一步:更新登录信息 。在放行请求前,拦截器会调用 redisTemplate.expire(key, time) 方法,刷新 Redis 中该 Token 键的过期时间。这就实现了你所说的"更新用户登录信息",即只要用户持续活跃,登录状态就会自动续期。

📊 两种方案对比

对比维度 基于 Session 的共享方案 基于 Redis 的 Token 方案
核心思想 改造原有 Session,使其存储于外部 Redis。 完全放弃 Session,采用无状态的 Token 机制。
数据存储 仍保留 Session 概念,但数据在 Redis。 无 Session,用户数据以 Hash 形式存于 Redis。
客户端凭证 JSESSIONID (通过 Cookie 传递)。 自定义 Token (通常在请求头传递)。
适用场景 传统服务端渲染项目改造。 前后端分离、微服务、移动端 App。
优点 对原有代码侵入性相对较小。 无状态、扩展性强、跨平台支持好。

总而言之,你的理解非常到位。第一种方案是为了解决 Session 在集群下的共享难题,而第二种方案则是一种更优的实践,它不仅解决了共享问题,还通过 Token 和拦截器实现了灵活的登录状态管理和自动续期。

相关推荐
英俊潇洒美少年3 小时前
Vue 生产环境打包:SourceMap、压缩、混淆、加密全解 + 最佳实践
前端·javascript·vue.js
巴博尔4 小时前
UNIAPP中NVUE页面 动画
android·前端·javascript·ios·uni-app
猫头虎-前端技术4 小时前
JS 作用域与闭包:从变量提升到闭包陷阱的超详细解析
开发语言·javascript·云计算·bootstrap·ecmascript·openstack·perl
洛水水5 小时前
Redis 分布式锁详解:实现与缺陷
数据库·redis·分布式
她说人狗殊途6 小时前
基于 vue-cli 创建
前端·javascript·vue.js
AZaLEan__6 小时前
前端移动端适配与 Bootstrap
前端·bootstrap·html
大家的林语冰7 小时前
Deno 2.8 正式发布,再次超越 Bun,史上最大的次版本升级诞生!
前端·javascript·node.js
影寂ldy7 小时前
C#数组的属性和方法(Clear / Copy / IndexOf )
开发语言·javascript·c#
Brave & Real7 小时前
小程序 const 在js中以及与同类的var和let之间的差异
javascript·微信小程序·小程序
tongluowan0077 小时前
Redisson的参数及工作原理
java·redis·lua·分布式锁