在现代 Web 应用中, 📱 手机号注册 & 登录 已成为一种常见的用户身份认证方式,特别是在移动端应用中,相比传统的用户名密码登录,它更加便捷,用户体验也更友好。本系列文章将详细介绍如何在 Next.js + MongoDB + Redis + JWT 的技术栈下,实现一个完整的用户管理系统。
本篇文章,我们将聚焦于 用户的手机号注册 & 登录,并搭建完整的 用户认证体系,包括:
🔹 用户注册 📝
🔹 用户登录 🔑
🔹 用户身份校验 🛡️
🔹 自动登录 & 退出登录 🔄
关于 短信验证码的发送与验证,将在下一篇文章中详细展开。
用通俗易懂的方式解释“登录”的逻辑
假设你有一个 私人俱乐部,只有注册会员才能进入。俱乐部的大门口有一个 保安(服务器),他的职责是:
- 核验会员身份
- 允许会员进入
- 不让陌生人随便进来
- 记录会员访问情况
📌 登录的 4 个步骤
🔹 第 1 步:用户来到了俱乐部(输入手机号)
- 用户在你的 网站(前端)上输入自己的 手机号,然后点“获取验证码”。
- 服务器 负责检查:
- 这个手机号格式对不对?
- 这个手机号是不是之前注册过?
- 生成一个验证码,并通过短信发送给用户。
- 把验证码存进“记事本”(数据库 / Redis),比如:
CopyEdit
手机号:13512345678
验证码:873451
过期时间:5分钟后
🔹 通俗理解:
你来到俱乐部,跟保安说:“我是会员,能进去吗?”
保安问你:“请出示你的会员卡(手机号),我核对一下。”
你提供手机号后,保安给了你一个 临时密码(验证码),并告诉你:“5 分钟内输入这个密码才能进去,否则过期无效。”
🔹 第 2 步:用户输入验证码
- 用户收到验证码 873451,然后在网站上输入。
- 服务器 检查:
- 验证码对不对?
- 验证码有没有过期?
- 如果正确,说明你是本人,登录成功。
- 如果错误,登录失败,让用户重新输入验证码。
🔹 通俗理解:
你拿着临时密码去找保安,保安检查密码是否正确:
- ✅ 密码正确:“欢迎光临,请进!”
- ❌ 密码错误:“密码不对!你可能不是会员。”
- ⏳ 密码过期:“抱歉,密码过期了,请重新申请。”
🔹 第 3 步:服务器给你发一张“通行证”(Token)
- 服务器发现你是合法用户,就给你发一张通行证(JWT Token)。
- 这张通行证可以让你自由进出,不用每次都重新验证手机号。
- 服务器不会记住你,而是每次你来都要求你出示通行证(Token)。
- Token 可能会设置一个过期时间,比如 7 天后自动失效。
🔹 通俗理解:
保安检查完你的会员卡(手机号 + 验证码),确认你是会员后,给了你一张 临时会员卡(Token)。
- 你下次再来俱乐部时,只要出示这张卡(Token),就可以直接进,不用再输验证码。
- 但这张卡 有有效期(比如 7 天后失效),到期后你就要重新用手机号+验证码登录。
🔹 第 4 步:每次访问都要带上“通行证”
- 以后 每次用户访问需要登录的页面(比如 VIP 会员专区),前端都会把 通行证(Token) 带上。
- 服务器会检查:
- 这张 Token 是否有效?
- Token 有没有过期?
- Token 属于哪个用户?
- 这个用户是不是 VIP 会员?
🔹 通俗理解:
你拿着临时会员卡(Token)去俱乐部游泳,保安看了一眼:
- ✅ 会员卡有效:“请进!”
- ❌ 会员卡失效:“你的通行证过期了,请重新登录!”
🎯
登录 = 进入私人俱乐部
- 你需要 手机号(会员身份)
- 你要 输入验证码(验证你是本人)
- 保安(服务器)会给你一张 通行证(Token)
- 以后你再来俱乐部,只要 带着通行证,就能自由进出 🎉
数据存储 & 技术选型
功能 | 方案 | 作用 |
---|---|---|
📂 用户信息存储 | MongoDB | 存储手机号、密码(加密后)、用户身份等信息 |
🔐 身份认证 | JWT(JSON Web Token) | 生成通行证,保持用户登录状态 |
💾 验证码存储 | Redis | 存储短信验证码,5 分钟后自动删除(防止数据库存储过多无效数据) |
🔄 会话管理 | HttpOnly Cookie | 让 Token 更安全,防止 XSS 攻击 |
👥 统一用户管理 | AuthContext(前端)+ API(后端) | 让前端全局管理用户登录状态,后端提供 /api/auth/me 供前端获取用户信息 |
🔹 Token 存储在哪里比较好?
在 Web 开发中,前端需要存储 JWT Token,以便后续请求时携带认证信息。目前主流存储方式有以下几种:
方式 | 位置 | 适用场景 | 优缺点 |
---|---|---|---|
HttpOnly Cookie ✅(推荐) | document.cookie | SSR 应用(Next.js API Routes) | 安全(HttpOnly & Secure),防止 XSS 攻击,但跨域请求需配置 CORS |
LocalStorage | localStorage.getItem("token") | SPA 前端(React/Vue) | 易于管理,但容易受到 XSS 攻击 |
SessionStorage | sessionStorage.getItem("token") | 仅当前会话有效 | 浏览器关闭后自动清除,适用于短时认证 |
💡 推荐使用 HttpOnly Cookie
- 防止 XSS 攻击:LocalStorage 可以被 JavaScript 代码读取,容易受到 XSS 攻击,而 Cookie 可设置
HttpOnly
,前端无法访问。 - 自动携带:使用 Cookie 存储 JWT,浏览器会在 每次请求时自动携带 Token,无需手动添加
Authorization
头部。 - 适合 SSR:如果你的 API 需要 SSR(如 Next.js API Routes),Cookie 方式更加友好。
🔹 为什么使用 MongoDB?
- JSON 友好:数据存储格式天然适配前端 JSON 数据结构,避免了数据格式转换问题。
- 扩展性强:相比于 MySQL,MongoDB 是 NoSQL 数据库,支持 灵活的数据结构,适用于 用户信息、日志、配置数据等存储。
- 更适合高并发:MongoDB 采用 文档存储,避免了传统 关系型数据库 的 JOIN 查询开销,提高查询效率。
那么,可以用 MySQL 吗?
可以,但 MySQL 适用于结构化数据(订单、库存管理等),而 MongoDB 更适合用户数据、认证信息等场景。在本项目中,MongoDB 更加灵活,因此是更好的选择 ✅
🔹 为什么要用 Redis?不用 Redis 行不行?
在本项目中,我们用 Redis 来存储 短信验证码,那么问题来了——为什么不用 MongoDB,而要引入 Redis?
✅ 使用 Redis 的优点:
- 自动过期机制:验证码通常是 5 分钟有效,使用 Redis 可以直接设置
EX
过期时间,过期后自动删除数据。 - 高效读取 & 低延迟:Redis 作为 内存数据库,读写速度远超 MongoDB,非常适合 短时存储 的数据(验证码、Token 黑名单等)。
- 限制验证码滥用:可以在 Redis 里设置 发送次数 & 失败次数限制,防止恶意攻击。
❌ 如果用 MongoDB 存验证码,会有什么问题?
- 需要手动清理过期数据,否则数据库会积累大量无效验证码数据。
- 读写性能较低,MongoDB 适用于 长时间存储 的数据,而验证码是 短期有效,不适合存数据库。
💡 结论:Redis 更适合存验证码等短时数据,MongoDB 适合存用户信息等长期数据。
🔹 为什么要用 AuthContext?
在 Next.js(React) 中,我们希望在前端全局管理 用户登录状态,因此可以使用 AuthContext 进行状态管理。
AuthContext 的作用:
- 全局管理用户状态,让应用任何页面都能访问
useAuth()
获取用户信息。 - 提供
login()
&logout()
方法,让用户可以在任何组件中触发登录/登出。 - 让用户自动登录,当 Token 仍然有效时,前端可以自动获取
me
接口,保持登录状态。
📌 如果不使用 AuthContext,会发生什么?
- 每个页面都需要 手动调用 API 获取用户信息,代码冗余。
- 组件之间不能共享用户登录状态,每次切换页面都会丢失登录信息。
💡 使用 AuthContext 后,整个应用可以随时访问用户状态,无需手动管理 Token!
总结
本篇文章介绍了 Next.js + MongoDB + Redis + JWT 技术栈下的 手机号注册 & 登录系统,并实现了:
✅ 手机号注册 & 登录 🔑
✅ JWT 认证 & 自动登录 🔄
✅ 获取当前用户信息 & 退出登录 🛡️
同时,我们探讨了 Token 存储方式(推荐 HttpOnly Cookie)、MongoDB vs MySQL、Redis 处理验证码的优势 以及 AuthContext 统一管理用户状态 的必要性。
📌 下一篇文章 将详细讲解 短信验证码的发送 & 验证,让用户可以 手机号 + 验证码登录。