基于 Redis 状态机的 APP 扫码登录深度实现

基于 Redis 状态机的 APP 扫码登录深度实现

业务场景背景在企业级 ERP 系统中,网页端(SaaS 管理后台)往往承载着敏感的财务与人事数据。传统的账号密码登录存在被监听或撞库的风险。APP 扫码登录利用手机端已有的安全上下文(如指纹、面容识别后的登录态),为 PC 端提供了一种既快捷又安全的身份穿透方案。

核心交互流程架构

该功能本质上是一个跨端同步的状态机。通过 Redis 作为中转站,将“网页端”、“后端服务”与“移动端”三方串联。

阶段一:凭证初始化(网页端)
网页端加载时调用 getQRToken 接口。

逻辑:生成全局唯一的 qrToken(二维码令牌)。

存储:在 Redis 中存入两个 Key:一个记录 Token 本身,另一个作为“读取状态位”(初始值为 0: 未扫描)。

安全:设置 5 分钟有效期,超时自动失效。

阶段二:身份关联与预授权(移动端扫码)
用户使用已登录的手机 APP 扫描二维码,调用 scanCode 接口。

校验:后端通过 JWTUtils 校验 APP 端的合法性。

信任传递:后端生成一个随机的 preToken(预登录令牌),并更新 Redis 状态为 1: 已扫描,同时关联此 preToken。

返回:将 preToken 返回给手机端,作为后续“确认登录”的唯一凭证。

阶段三:状态探测(网页端轮询)
网页端通过 codeHasBeenRead 接口进行高频轮询(或使用 WebSocket)。

数据解析:后端拆分 Redis 里的字符串(如 1,preToken)。

UI 反馈:网页端一旦拿到状态 1,立即从二维码界面切换为“扫码成功,请在手机确认”的提示状态。

阶段四:最终授权(移动端确认)
用户在手机上点击“确认登录”,调用 goQRLogin 接口。

对暗号:APP 携带 preToken 请求,后端比对 Redis 中的 preToken 是否一致。

暂存信息:比对成功后,将该用户的信息(Users)暂时缓存至 Redis 的临时区域。

阶段五:令牌核发(网页端进入)
网页端发起最后的 checkLogin 调用。

JWT 颁发:后端从 Redis 提取暂存的用户信息,使用 jwtUtils.createJWTWithPrefix 生成 SaaS 平台专属的 JWT。

会话建立:网页端拿到正式令牌,完成登录并进入 ERP 系统主页。

核心代码实现细节

在轮询接口中,通过简单的字符串分割实现高效的状态判定:

1
2
3
4
5
6
7
8
9
Java
String readStr = redis.get(SAAS_PLATFORM_LOGIN_TOKEN_READ + ":" + qrToken);
if (StringUtils.isNotBlank(readStr)) {
String[] readArr = readStr.split(","); // 格式如 "1,uuid-preToken"
if (readArr.length >= 2) {
list.add(Integer.valueOf(readArr[0])); // 状态码: 1
list.add(readArr[1]); // preToken
}
}

预登录令牌(preToken)的安全价值

preToken 是该方案的安全灵魂。它确保了:

防伪造:只有真实扫过码的手机才能拿到 preToken,攻击者无法通过模拟请求直接进入登录环节。

链路锁定:确保了最后确认登录的手机与显示二维码的网页窗口是一一对应的“信任链路”。

技术亮点与架构思考

无状态化设计:整个过程不依赖 Session,完全由 Redis 维护状态,天然支持集群部署和横向扩展。

多端身份解耦:APP 令牌与 SaaS 令牌前缀不同、有效期不同,实现了移动端与管理后台的权限体系隔离。

防御性编程:在 checkLogin 环节,通过 UUID 和短时效 Redis Key 确保了令牌的一次性,有效防止了重放攻击。

总结

扫码登录不仅是用户体验的优化,更是企业安全策略的延伸。通过 Redis 状态机 + 双重 Token 校验,我们实现了一个低耦合、高可靠的跨端身份认证体系,为 ERP 系统的数据安全构筑了坚固的第一道防线。

负责了 ERP 系统的跨端统一身份认证中心。重点攻克了扫码登录过程中三方状态同步的问题,通过设计一套基于 Redis 的双令牌(qrToken/preToken)确认机制,解决了跨设备信任传递的安全难题。该方案不仅提升了 HR 用户的办公效率,还通过无状态 JWT 颁发机制支撑了系统的高并发访问。”