现在几乎所有的App都支持多个第三方账号登录(微信、QQ、微博等),这就是多账号统一登录。账号表设计与流程设计如果不到位,后续扩展会非常困难。
本文不提供具体的代码实现,而是结合我在公司负责账号模块的实践经验,梳理一套通用的设计思路,供大家参考。
一、自建的登录体系
1.1 手机号登录注册
思路:每个手机号对应一个用户,手机号为必填项。
流程:
- 用户输入手机号,发送到服务端。服务端先判断该手机号是否存在账号;如果没有,则生成随机验证码,将手机号和验证码绑定到
Redis,并设置过期时间(通常5分钟),然后将验证码通过短信发送给用户。
- 用户收到验证码后,在界面填写验证码、密码等基础信息,提交到服务端。服务端验证
Redis 中该手机号对应的验证码是否一致——不一致则返回错误码;一致则创建账号并保存密码。
- 注册成功后,用户可通过
手机号+密码 登录。
问题:
- 用户体验差:需要获取验证码、填写验证码/密码/用户名等大量信息才能完成注册。
- 容易遗忘密码:忘记后只能通过“忘记密码”重新设置。
1.2 优化注册登录
思路:弱化密码的必填性,无论用户是否注册过,均可通过 手机号+验证码 直接登录(同时保留 手机号+密码 方式)。
流程:
- 输入手机号,发送到服务端。服务端生成随机验证码,绑定到
Redis 并设置过期时间,通过短信发送。
- 用户填写收到的验证码,提交到服务端。服务端验证验证码是否一致——失败则返回错误码;成功则直接登录。如果是老用户,拉取用户信息;如果是新用户,提示可完善信息(不强制)。
- 用户通过
手机号+验证码 登录后,也可选择设置密码,以后即可使用 手机号+密码 登录。密码变为非必填项。
用户表设计:

1.3 引入第三方账户方案
1.3.1 微博登录
进入 Web2.0 时代,微博开放了第三方网站登录。产品要求:用户能用微博账号登录我们的 App,并且和自有用户表关联。
流程:
- 客户端调用微博登录界面,用户输入用户名、密码,登录成功后返回
access_token。通过 access_token 调用 API 接口获取用户信息。
- 服务端根据用户信息在用户表中创建一个账号。此后,该第三方账号即可直接通过微博登录。
微博用户信息表设计:

1.3.2 噩梦来临
紧接着,QQ、微信、网易等纷纷开放用户登录。如果按照“微博用户信息表”的方式为每家新建一张表、写一套登录逻辑,扩展性会变得非常糟糕。
二、优化账号体系
2.1 原账号体系分析
- 自建登录体系:无论是
手机号+密码 还是 手机号+验证码 ,本质上都是 用户信息+密码 的验证形式。
- 第三方登录:也是
用户信息+密码 的形式——用户信息是第三方系统中的唯一标识(ID),密码则是 access_token(一种有使用时效、定期修改的密码)。
2.2 新的账号体系
2.2.1 数据表设计
用户基础信息表:

用户授权信息表:

说明:
- 用户表拆分为
用户基础信息表 + 用户授权信息表。
- 用户信息表不保存任何密码或登录信息(如用户名、手机号、邮箱),只保留昵称、头像等基础信息。所有与授权相关的内容都放在用户授权信息表中,用户信息表和用户授权信息表是一对多的关系。
2.2.2 登录流程
- 手机号+验证码:沿用之前的方案。
- 邮箱/手机号+密码:用户填写
邮箱/手机号+密码;请求登录时,先判断类型。以手机号登录为例:使用 type='phone' 结合 identifier='手机号' 查找,取出并判断 password_hash(密码)是否与当前条目的 credential 相符,相符则通过验证,然后通过 user_id 获取用户信息。
- 第三方登录(如微信登录):查询
type='weixin' 结合 identifier='微信 openId'。如果有记录,则直接登录成功并更新 token;在假设与微信服务器通信不被劫持的情况下,无需判断凭证问题。
2.2.3 优缺点
优点:
- 登录类型便于扩展,新增登录类型的开发成本显著降低。
- 原来需要验证手机号/邮箱是否已验证时,需要额外字段(如
phone_verified、email_verified);现在只需在用户授权信息表中增加一个统一的 verified 字段,每种登录方式均可直观显示验证状态。
- 在用户授权信息表中添加时间和 IP 地址,可以更完整地跟踪用户使用习惯(例如:已不再使用微博登录两年多、已绑定微信 300 天)。
- 邮箱和手机号仍可保留在 users 表中,但只作为“展示用途”,与昵称、头像等属性本质相同。
- 可按需绑定任意数量的同类型登录方式(如一个用户可绑定多个微信、多个邮箱、多个手机号)。当然也可以限制每种登录方式只能有一条记录。
缺点:
- 当用户同时拥有邮箱、用户名、手机号等多种站内登录方式时,修改密码必须统一修改,否则会出现
邮箱+新密码 和 手机号+旧密码 都能登录的矛盾情况。
- 代码量和逻辑判断增加,复杂度上升。例如:无论用户是否已登录、是否已注册,都通过同一链接前往微博第三方授权后返回,可能产生多种分支情况:
- 该微博在本站未注册过:直接注册关联并登录。
- 该微博已在本站存在,当前用户未登录:直接登录成功。
- 该微博未在本站注册,但当前用户已登录且已关联另一个微博账号:处理方式取决于是否允许绑定多个微博账号。
- 该微博未在本站注册过,当前用户已登录:尝试进行绑定操作。
- 该微博已注册,用户又使用该账号登录:为何重复绑定自己?
- 该微博已存在,但当前用户已登录且关联的是另一个微博账号:如何处理?
三、一键登录
3.1 背景
回顾 手机号+验证码 的登录方式:
- 输入手机号、等待验证码短信、输入验证码、点击登录,整个流程可能需要 20 秒以上,操作繁琐。
- 依赖短信网络,若收不到短信则无法登录。
- 存在验证码泄漏风险——有人知道你的手机号并窃取验证码,就能登录你的账号。
那么,我们为什么需要验证码?验证码的作用是确认该手机号属于你。除了短信,是否还有其他认证方式?
- 如果能获取当前使用的手机号,就能直接验证。但出于安全考虑,客户端无法直接获取手机号,运营商可以通过 SIM 卡数据查询到。
- 现在运营商已开放相关能力:用户输入手机号后,调用运营商的接口判断输入的手机号是否与本地号码一致。这样用户就无需等待验证码短信,不受短信网络限制。
- 更进一步,如果运营商能直接把当前号码返回给应用,用户连手机号都不需要填写了。
这就是 一键登录。
3.2 本机号码认证
获取当前手机使用的 SIM 卡号,直接使用该号码登录,即为一键登录。
这种方式的优势显而易见:将原本可能 20 秒的流程缩短至 2 秒左右,极大提升用户体验。
主要步骤:
- SDK 初始化:调用 SDK 的初始化方法,传入项目在平台上的 AppKey 和 AppSecret。
- 唤起授权页:调用 SDK 唤起授权接口。SDK 先向运营商发起获取手机号验码的请求,请求成功后跳转到授权页。授权页会显示手机号掩码以及运营商协议供用户确认。
- 同意授权并登录:用户同意协议并点击授权页的登录按钮,SDK 请求本次取号的 token,请求成功后返回 token 给客户端。
- 取号:客户端将获取到的 token 发送到自己的服务器,服务器携带 token 调用运营商的一键登录接口,成功则返回手机号码。服务器用该手机号进行登录或注册操作,返回结果给客户端,完成一键登录。
四、小结
没有最好的方案,只有最适合当前系统的设计。不必深究孰优孰劣,鞋合不合脚只有脚知道。
如果您对账号体系设计有不同的思路或经验,欢迎在 云栈社区 一起交流探讨。
|