App与服务器保持会话的核心方式是使用Token令牌机制:客户端登录后获取短期有效的访问令牌,配合长期有效的刷新令牌,每次请求都携带令牌让服务器验明身份,到期后自动续期,从而维持稳定的登录状态。这套机制取代了早期Web时代依赖Cookie的做法,成为移动端会话管理的主流方案。
app和服务器之间的会话是怎么建立起来的?
如果把App比作一位常客,服务器就是一家安保严格的餐厅,第一次光临时,你要出示身份证明(账号密码),餐厅发给你一张临时通行证(Token),之后每次进出,都只需要亮一下通行证,不用再重复出示身份证。
登录那一刻发生了什么
- 用户输入账号密码,App发起登录请求。
- 服务器验证通过后,生成一串加密字符串(Token),返回给App。
- App把Token存储在本地安全区域,每次请求接口时,在请求头里带上它。
- 服务器收到请求后,先验Token,有效就放行,无效或过期就返回401状态码。
这套流程中,Token本身携带用户的身份标识和过期时间,服务器不需要保存会话记录,这就是行业共识中的无状态会话设计,它让服务器可以轻松横向扩容,因为任何一台服务器都能独立验证Token,不需要共享内存中的Session数据。
服务器怎么认出你的Token
服务器验Token并不是去数据库逐条比对,而是用签名算法对Token进行校验,业内常用JWT(JSON Web Token)格式,Token包含三段信息:头部、载荷、签名,只要密钥不泄露,任何人无法伪造签名,Token自然无法冒充。
现实中遇到的一个场景是:用户清除了App的缓存数据,再打开时发现登录状态还在,这是因为iOS的钥匙串或Android的Keystore具有持久化能力,删除App数据不一定能清掉这些安全区域里的Token,反过来,用户卸载重装后往往会发现需要重新登录,这说明当年的Token已被系统级存储机制清除。
app token过期怎么处理?双token机制在背后兜底
网上搜索“app token过期怎么处理”能翻到大量开发者的求助帖,答案指向同一个方案:给Token加一个“替补队员”。
access token和refresh token的分工
Token不能永远不过期,否则一旦泄露就被人永久冒用,但如果过期太快,用户频繁重新输入密码,体验又很差,双Token机制就是为这组矛盾设计的。
| 类型 | 有效时长 | 主要职责 | 存储位置 |
|---|---|---|---|
| Access Token | 短(15分钟-24小时) | 每次请求验证身份,频繁使用 | 内存或安全存储 |
| Refresh Token | 长(7天-30天) | 获取新的Access Token,低频使用 | 安全存储,密钥保护 |
大部分App平时只在内存中持有Access Token,一旦它过期,App会悄悄拿Refresh Token去换新的,整个流程用户无感知,只有Refresh Token也过期时,才会真正弹出“登录已过期”的提示。
刷新失败的常见场景
- 用户长期未打开App,Refresh Token超过有效期。
- 服务端检测到异常登录,主动吊销了Refresh Token。
- 手机本地时间乱跳,导致请求头里的时间戳超出容忍范围。
- 企业自建证书的App换了打包证书,验签直接失败。
遇到这些情况,App只能引导用户重新登录,近几年多数主流App都在用的策略是:优先静默续期,静默失败之后才让用户主动感知,这比直接踢用户下线要温和得多。
websocket断线重连怎么实现?心跳机制是保活的基础
有些场景不能等用户下一次点击才去拉数据,比如聊天消息、股票行情、协同编辑,这时App需要和服务器建立一条长连接,行业叫WebSocket,但移动网络不像Wi-Fi那么稳定,穿隧道、过电梯、丢信号都会造成连接断开,重新连上服务器,也是一项成熟的技术活。
先说断线是怎么被发现的
TCP连接本身在一段时间内没有数据传输时,处于“假活”状态,任一方断开都没有提示,比如你把手机开飞行模式,服务器可能几分钟内都以为连接还在,心跳包的作用就是定时告诉对端“我还活着”。
具体操作流程是:
- 客户端每30秒发送一个极小的ping数据包。
- 服务器收到后返回pong数据包。
- 连续三次没收到pong,客户端主动关闭旧连接。
- 随即发起重连,并带上当前用户的Token完成身份认证。
- 重连成功后,服务器把离线期间的消息补推给客户端。
重连策略别用固定间隔
简单写一个定时器每隔一秒重连一次,会造成“重连风暴”大量客户端同时崩溃、同时重连,服务器被请求淹没,行业里普遍采用指数退避算法:第一次等1秒,第二次等2秒,第三次等4秒,最大间隔封顶在60秒左右,并且随机化抖动,每个客户端错峰重连,服务器压力就降下来了。
在重连过程中要留意Token状态:如果App的Access Token已经过期,应该先去刷新Token,再用新Token重建WebSocket,部分开发者在WebSocket回调里只处理网络断开,忽略了Token过期这一层,就导致用户一直转圈连不上,实际上服务端日志显示的是签名校验失败。
小程序和app的会话机制有什么区别?
小程序是一个特殊的“App分包”,它的会话保持与原生App既有相似又有差异,搜索“小程序和app的会话机制有什么区别”时,开发者通常关注的是微信生态下的身份认证环节。
认证入口不同
原生App用账号密码登录,小程序通常用微信授权登录,小程序前端调用 wx.login 拿到临时code,传给开发者服务器,服务器再用code向微信服务器换取 openid 和 session_key,这个session_key是解密微信用户信息的关键,但它不是你自己服务端的登录凭证。
权限粒度不同
原生App的Token可以自定义过期时间和权限范围,可以在服务端随时吊销,小程序的code有效期只有5分钟,且微信官方限制不能频繁调用 wx.login,短时间内多次调用会导致同一会话返回错误码,开发者需要自己生成业务Token来维持登录态,不少团队在此处误将session_key当业务Token下发,结果用户换手机后无法解密手机号信息。
另一个差异体现在生命周期上:原生App常驻后台,自己控制WebSocket心跳;小程序被微信切后台就可能被冻结,等用户回到前台时,WebSocket大概率已断开,需要监听 onShow 事件做恢复重连,而不是靠定时器保持心跳。
app登录状态经常失效是什么原因?
用户的直觉是“App偷偷把我登出了”,从工程视角看,绝大多数情况是Token相关的几个环节出了问题:
服务器时间不准带来连锁反应
JWT的过期校验依赖服务器时间戳,如果服务器时钟漂移严重,Token可能提前几秒被判过期,前端拿到401后尝试刷新,刷新接口的Refresh Token也因同一个问题失效,直接进入重新登录流程。
单点登录没做全局会话管理
一些App支持微信、手机号、苹果ID三种方式登录同一个账号,如果登录态只绑定设备ID,不绑定用户的唯一标识,就会出现换绑手机号后旧会话仍然有效的漏洞,反之,如果要求在任意一端登出后所有端都下线,则需要在服务端维护会话版本号,每次登录生成新的版本号,旧Token的版本号不匹配就失效。
应用更新导致SecurityContext丢失
部分App把Token存在SharedPreferences(Android)或UserDefaults(iOS),应用更新后这些数据一般保留,但如果应用强制升级后签名不一致,系统会直接丢弃数据区域,用户就被迫重新登录,头部大厂常用的做法是:在每次冷启动时先用本地Refresh Token检查有效性,再决定是否展示登录页,避免直接弹登录页吓到用户。
关于app会话保持的常见问题
为什么app偶尔会弹出“登录已过期”?
多数情况是Refresh Token已失效,服务器无法静默续期,触发因素包括:长期未打开App、服务端主动吊销、账号在其他设备改密,App此时只能让用户重新走一遍登录流程。
服务器重启会导致App掉线吗?
由于Token是无状态签名机制,重启后验签逻辑不变,已登录用户通常不受影响,但WebSocket连接需要重新建立,业务侧需要把在线状态、未读消息等数据从持久化存储中恢复出来。
换设备登录后旧设备会掉线吗?
取决于是否启用了单点登录且强制踢人下线策略,默认情况下,多数App允许同一账号在多台设备登录,旧设备Token仍然有效;部分金融类、WebRTC场景会启用“同账号同端”策略,新设备登录后旧Token立即失效,旧设备收到401后跳转登录页。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/785213.html


