基于 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 和拦截器实现了灵活的登录状态管理和自动续期。

相关推荐
Filwaod3 小时前
互联网大厂Java面试实战:Spring+Redis+MySQL+JVM场景问答深度解析
jvm·spring boot·redis·mysql·java面试·技术面试·互联网大厂
时光足迹4 小时前
Tiptap之标注组件
前端·javascript·react.js
Filwaod4 小时前
Java面试现场:从Redis缓存到分布式事务,水货程序员李四的‘表演‘
java·jvm·spring boot·redis·mysql·面试·多线程
Filwaod4 小时前
互联网大厂Java面试实战:从Spring Boot到AI智能客服,水货程序员李四的翻车现场
spring boot·redis·mysql·spring cloud·微服务·ai·java面试
时光足迹4 小时前
Tiptap 之自定义脚注组件
前端·javascript·react.js
时光足迹4 小时前
Tiptap之造字组件
前端·javascript·react.js
小四的小六4 小时前
WebView 兼容性踩坑实录:那些让我加班的坑
javascript·webview
jump_jump4 小时前
用官方模板理解 Decky 插件:一次从模板到架构的速览
javascript·python·游戏
张元清4 小时前
React 表单处理:防抖校验、自动保存草稿与受控输入
前端·javascript·面试