会话与登录登出:两套凭证、冷启动恢复,以及为什么过期就登出

项目 social-app

  • 登录
  • 会话
  • 即时通讯
  • 登出
  • 游客

1. 背景与问题

这是一款面向日本市场的语音社交 App。用户眼中只有「登录」和「退出」。客户端里其实有三套互不替代的凭证:

  1. 业务会话:登录接口随用户资料一起返回,之后每次业务请求放在 Cookie 里。
  2. 即时通讯票:再向业务服务要一张,交给第三方 IM SDK。登录回包里也会带一份,但自动登录读的是另一处本地缓存。
  3. 房间音视频票:进房时下发,只服务这一次进房。到期回调只记日志,不续票。

这篇讲这三套凭证怎么来、冷启动怎么决定进首页还是登录页,以及过期之后为什么选择登出而不是刷新。游客登录、卸装后恢复同一游客号、游客转正、注销账号、资料和选圈子,是在这套底座上补上的;会话归档、Cookie、登出去重和即时通讯自动登录本身是团队方案。


2. 三套凭证

语音房即时通讯业务会话
会话标识放进 Cookie通讯票和账号偏好里的那一份进房时下发到期只记日志登录成功进入房间
种类 从哪来 放在哪 失效时怎么处理
业务会话 登录回包 用户归档和内存 业务码触发登出,不换新凭证
即时通讯票 再向业务服务要;回包里也有一份 偏好设置。归档里那份不用于自动登录 需要换票的错误会清掉本地票再要;尝试登录失败最多再要 5 次
房间票 进房接口 房间模型 到期只记一条错误日志并上报,不续

回包里没有刷新用的凭证,也没有业务会话的过期时间。客户端因此无法在本地判断「这张票还剩多久」。

账号容器当前用户登出通知只发一次用户会话标识资料通讯账号游客凭证业务请求Cookie 带会话标识没有刷新通讯管理偏好里的票最多再要 5 次房间进房票到期只记日志

游客凭证是例外:它进系统钥匙串,另外还有一份游客归档,用来认出「现在是游客」以及卸装重装后找回同一个号。普通登出故意留着这两份,否则重装就变成新游客。


3. 登录入口和成功之后

登录页上的通道是 Apple、Google、LINE、Twitter 和游客。没有手机号、短信或邮箱登录。资料里的手机和邮箱来自资料接口,不是登录通道。

三方登录先拿授权,再交给对应的业务登录接口,成功返回完整用户。Apple 的全名只在第一次授权时给出,所以会缓存在钥匙串里。游客登录如果钥匙串里已经有凭证就带上,否则空着去申领。

即时通讯根页账号业务服务授权或钥匙串登录页用户即时通讯根页账号业务服务授权或钥匙串登录页用户alt[资料还没完-成]选择渠道或游客授权,或读游客凭证换成业务会话用户、会话标识、通讯账号写入归档资料页,再选圈子登录通知切到首页,绑定推送这时才登即时通讯

资料未完成的新用户会先去资料页(昵称、性别、出生日期、头像),再到选圈子。选圈子提交时如果还没有账号,会在这里补一次游客登录。游客登录失败时展示服务端错误,而不是一直转圈。已经有完整资料的用户则直接发登录通知。

根页收到通知之后才切首页、绑定推送,并尝试登录即时通讯。业务登录接口返回时,即时通讯还没登完。


4. 冷启动:只看本地,不问服务器

启动时会准备日志、推送、三方平台和即时通讯 SDK,但这里不登录。账号容器第一次被用到时,把归档里的用户解出来。根页再做决定:

没有有,资料未完成有,资料已完成
冷启动解出本地用户?登录页首页根页出现再登即时通讯

没有一步用会话标识去问服务器「这张票还有效吗」。资料是否完成:审核包看新手标记,否则看性别是否仍未知。因此「归档还在,但资料没填完」会回到登录页,而不是直接打开资料页。游客可以凭钥匙串再登,再走进资料流。

登录成功冷启动且资料完成冷启动但资料未完成根页出现自动登录或换票成功过期、被踢或封停
未登录已归档首页登录页通讯登录中可用

5. 过期就登出,不刷新

发请求之前不检查会话是否过期。这次请求的业务码说无效、过期、非法、被其他端踢下线,或者账号封停,就立刻发登出通知。注释写的是「过期了」,实际把非法登录、被踢和「请求过期」都算进去。

多个请求一起失败时,靠一个一次性标志:已经发过通知就忽略,下次登录成功再复位。即时通讯的被踢弹窗还在时,先不发通知,等用户点确定。登出之后不会自动重放刚才那次请求,因为没有「先刷新再重放」这条路。

这是当时选定的设计:客户端保持简单,有效性完全交给服务端。代价写在第 8 节,那些改进都还没有做。


6. 即时通讯票

冷启动或根页出现后:如果偏好里的通讯账号和当前用户一致,就用已有的票自动登录;否则向业务服务要一张新的再登。所以登录回包里即使已经带着通讯票,客户端仍常常会再要一次。

已经登录正在登录本地票对得上对不上成功需要换票账号封禁
成功失败且未满 5 次超过 5 次
检查已在线跳过自动登录向业务要票清票再要登出尝试登录再要票可能卡住

被踢的处理分三种:封禁先提示「账号已被封禁」再登出;其他由服务端发起的踢,直接登出,没有额外文案;不是服务端踢的(其他设备登录)先提示再登出。自动登录若遇到需要换票的错误,清掉本地票再走一遍;账号封禁则登出;操作过于频繁则尝试回传即时通讯 SDK 的日志。

业务请求上的「被其他端踢下线」不会弹出「已在其他设备登录」,只发登出通知,用户直接看到登录页。和即时通讯被踢的提示不一致。

票或账号为空时,尝试登录只会记一条日志,但「正在登录」可能已经置上。超过 5 次仍失败时,这个标志也可能没有复位。两种情况都要走到登出或杀掉进程才能再登。


7. 主动退出和强制登出

用户在设置里确认退出:如果还在语音房,先退房;然后先登出即时通讯。即时通讯失败就提示「退出登录失败」,本地会话保持不动。成功之后才解绑推送,并调用业务登出。业务登出是发出去就继续,不等它成功;通知和清本地多半已经发生。接口失败会提示,纯网络失败不再额外上报。

业务服务即时通讯语音房客户端用户业务服务即时通讯语音房客户端用户alt[即时通讯失败][成功]确认退出若在房中先退房登出失败提示,本地仍保持登录成功解绑推送业务登出,不等结果发登出通知并清本地

强制登出来自业务码,或即时通讯被踢,或自动登录发现账号封禁。这条路不调用业务登出,不解绑推送,也不清理三方 SDK 的登录态。

根页账号业务请求或即时通讯根页账号业务请求或即时通讯过期、被踢或封停若已通知过则忽略登出通知拆掉首页,切到登录页删用户归档,清内存配置取消上传,若仍在房则退房
清理项 用户主动退出 强制登出
先退出语音房 会 通知之后若仍在房则退
即时通讯登出 必须先成功 清本地时再做一次
解绑推送 即时通讯成功后做 不做
调用业务登出 会,但不等成功 不做
清理三方 SDK 登录态 不做 不做
删用户归档 即时通讯成功后做 会
保留游客钥匙串 会,为了重装恢复 会

根页收到通知后的共同清理是:拆掉首页、复位「是否进过首页」、切到登录页、把好友列表的刷新时间打回起点、删掉用户归档、清掉内存里的配置(下次请求会重新过配置门)、取消正在进行的动态上传并丢掉内存草稿、角标归零。圈子的归档文件这次清理未必会删,换账号后有短暂串数据的风险。


8. 取舍与可改进之处

下面每一条都是方向,不是已经做完的改动。

现在的做法 问题 改进方向
过期、非法、被踢、封停、请求过期都登出 「请求过期」更像时钟或时间戳问题,一并登出可能过激 把「请求过期」从登出集合里拆出去,先确认是不是有意
没有刷新,失败的请求也不重放 一次过期就要整段重新登录 单次刷新:进行中的请求先排队,换到新会话后再重放
强制登出不解绑推送、不调业务登出、不清三方 SDK 旧设备可能继续收到推送,服务端会话也可能还在 主动退出和强制登出走同一条清理
业务码被踢不提示,即时通讯被踢会提示 同一种「被顶下来」体验不一致 两种踢都先说明原因再进入登录页
业务会话放在文档目录的归档里 和钥匙串里的游客凭证、设备标识不是同一安全级别 会话标识改放钥匙串
即时通讯重试超过 5 次,进行中的标志可能还在 之后每次准备登录都以为正在登录 放弃时一定复位;票为空时不要先把标志置上
房间票到期只记日志 长房间里可能无声,而且日志里不该出现票本身 到期前向业务再要一张并更新进房;日志只记「到期」,不记票

另外两件已经能看出来、同样还没改:归档里的通讯票和偏好里实际用来登录的那份可能不一致;强制登出时房间页会不会被置空,取决于通知和清用户谁先谁后。


9. 游客、转正、注销和新手

游客登录:钥匙串里已有凭证就带上,否则首次申领。成功后凭证写入钥匙串,并另存一份游客归档,卸装重装后仍是同一个游客号。

游客转正用 Apple、Google、LINE、Twitter 之一绑定。成功就删掉游客归档和钥匙串里的游客凭证,之后用该三方账号登录。绑定失败只提示,游客态保留。

注销账号先查登录类型,再按原来的渠道重新授权,然后删号。确认页也会发同一套登出通知。

新手后半段是资料页再选圈子。资料包括昵称、性别、出生日期和头像。选圈子提交时如果还没有账号,就在这一步补游客登录。这一步失败要展示服务端返回的错误。选圈子是现在的主路径;更早还有选游戏,后来被选圈子取代。

申领或用钥匙串恢复登录后
提交时发现还没有账号绑定一个三方渠道成功按原渠道重新授权后删号绑定失败,游客态还在
无账号游客资料选圈子已注册已注销

普通登出不清游客钥匙串。这是为了重装后还能回到同一个游客号,不是漏删。