黑马点评-短信登录模块

一、整体技术栈

  1. 后端框架:Spring Boot + Spring MVC
  2. 缓存中间件:Redis(核心)
  3. 数据持久化:MySQL + MyBatis/MyBatis-Plus
  4. 工具 / 依赖:短信服务(第三方短信 API / 模拟接口)Hutool(工具类,验证码、字符串、时间处理)Lombok(简化实体类)RedisTemplate(Redis 操作模板)

二、核心业务流程(短信登录完整链路)

  1. 发送短信验证码前端传手机号 → 后端校验手机号格式 → 生成 6 位随机验证码 → Redis 存储手机号 + 验证码(设置过期时间) → 调用短信接口发送验证码到手机。
  2. 短信验证码登录 / 注册前端传手机号 + 验证码 → 后端从 Redis根据手机号查询验证码 → 校验验证码是否匹配、是否过期 → 校验通过:MySQL 查询用户,不存在则自动注册新用户生成全局唯一登录令牌(Token)Redis 存储 Token - 用户信息(登录态),设置过期时间返回 Token 给前端
  3. 登录状态校验(拦截器)前端请求头携带 Token → 自定义拦截器拦截请求 → 从 Redis 根据 Token 查用户 → 存入 ThreadLocal(线程本地)供全局使用 → 放行请求。
  4. 退出登录前端传 Token → 后端删除 Redis 中对应登录 Token 数据 → 清除 ThreadLocal 用户信息。

三、Redis 核心用法(本模块重点)

1. 数据结构选型 & 存储设计

表格

存储短信验证码

String

login:code:{手机号}

5 分钟(防长期占用、验证码时效)

存储登录用户态

String

login:token:{UUID令牌}

30 分钟(会话超时)

2. RedisTemplate 常用操作

  • 增:redisTemplate.opsForValue().set(key, value, 时长, 时间单位)(带过期时间)
  • 查:redisTemplate.opsForValue().get(key)
  • 删:redisTemplate.delete(key)
  • 判空:判断 Key 是否存在、Value 是否为空(验证码过期 / 未发送判断)

3. Redis 序列化问题(高频踩坑点)

  • 默认 JdkSerializationRedisSerializer:Key/Value 序列化后乱码、可读性差
  • 解决方案:配置 RedisTemplate 使用 Jackson2JsonRedisSerializer,实现 JSON 序列化,统一数据格式。

四、验证码相关知识点

  1. 手机号格式校验:正则表达式校验国内手机号规则
  2. 随机验证码生成:纯数字 6 位验证码(Hutool RandomUtil 工具)限制同一手机号频繁发送:Redis 判断login:code:{手机号}是否存在,存在则拒绝重发(防刷接口)
  3. 时效控制:依靠 Redis 自动过期,无需手动清理过期验证码。

五、登录令牌(Token)设计

  1. Token 选型:使用 UUID 生成全局唯一字符串,作为登录凭证
  2. 存储逻辑:Key:login:token:{UUID}Value:序列化后的用户 DTO(只存业务需要字段,脱敏,不存密码)
  3. 续期机制:每次用户发起请求,拦截器检测到有效 Token,重置 Redis 过期时间(滑动过期,保持登录)

六、身份认证:拦截器 + ThreadLocal(核心架构)

1. 自定义登录拦截器

  • 实现 HandlerInterceptor 接口,重写 preHandle 前置拦截
  • 逻辑:从请求头获取 authorization(前端携带的 Token)Token 为空 → 拦截,返回未登录Token 不为空 → 查询 Redis 用户信息无用户信息(Token 过期 / 无效)→ 拦截存在用户 → 存入 ThreadLocal,放行
  • 配置拦截器:WebMvcConfigurer 注册拦截器,设置放行路径(发送验证码、登录接口无需拦截)

2. ThreadLocal 线程本地存储

  • 作用:同一请求线程内全局共享用户信息,Controller/Service 无需重复传参、重复查 Redis
  • 规范:请求结束后(afterCompletion手动清除 ThreadLocal,避免内存泄漏、线程复用串数据。

七、业务逻辑:登录 & 自动注册

  1. 验证码校验失败:直接返回错误提示
  2. 验证码校验成功:根据手机号查询 MySQL 用户用户不存在:自动创建用户(手机号作为账号,密码可加密默认值)用户存在:直接复用
  3. 密码处理:新用户默认密码MD5 加密入库(基础密码加密知识点)

八、接口安全 & 防刷优化(面试重点)

  1. 防验证码刷接口同一手机号短时间内禁止重复获取验证码:Redis 存在验证码 Key → 直接返回 “请勿频繁发送”。
  2. 会话超时登录 Token 设置固定过期时间,结合滑动续期提升体验。
  3. 数据脱敏Redis 只存用户 DTO,不存明文密码、敏感字段。
  4. 接口无状态基于 Token+Redis 实现分布式会话(区别于传统 Session),支持集群部署。

九、Session vs Token(本模块核心思想)

  1. 传统 Session 登录:服务端内存存储 Session,集群需 Session 共享,扩展性差
  2. 本项目 Token 方案:服务端:Redis 分布式存储登录态客户端:存储 Token,每次请求携带优势:无状态、支持分布式、前后端分离、跨端使用

十、常见异常 & 踩坑总结

  1. Redis Key 乱码 → 序列化器配置错误
  2. 验证码明明正确却校验失败 → 前后端参数不一致、Redis 取值类型不匹配
  3. 登录后部分接口仍提示未登录 → 拦截器路径配置错误,未拦截受保护接口
  4. 多用户登录串号 → ThreadLocal 未及时清除
  5. Token 提前失效 → 过期时间设置错误、续期逻辑未实现
  6. 短信接口调用失败 → 第三方接口参数、签名、地址错误(本地可模拟短信)

十一、拓展延伸(后续模块铺垫)

  1. Redis String 结构的实战使用(后续点赞、签到、缓存都高频用到)
  2. 分布式登录、分布式会话基础
  3. 拦截器 + ThreadLocal 的通用权限校验模板(项目通用架构)
  4. 接口限流、防刷的基础实现思路
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务