本文的小程序应用是单独使用Cookie来维护登陆状态,登陆并未使用小程序的sessionKey来维护后台登陆状态。
1 问题描述 最近有用户反馈,小程序登陆有问题 小程序成功登陆后,安卓用户预约操作时,偶尔会出现登陆异常情况。登陆失败现象极其诡异,问题难以复现。 1 用户10秒前刚登陆,用户后续操作马上提示“登陆异常” 2 部分安卓用户在登陆后,在后续操作提示“登陆异常”,这种现象是偶然发生的,安卓用户出现登陆异常概率大概是10分之1。 2 苹果用户从未没有出现”登陆异常“现象。 2 登陆实现方案 在介绍问题前,本文先简单描述下本文应用登陆实现方案。 本文的小程序应用是单独使用Cookie来维护登陆状态,登陆并未使用小程序的sessionKey来维护后台登陆状态。 后端Cookie校验用户登陆状态为什么不使用小程序SessionKey维护登陆状态? 1 老应用有单独Cookie登陆方式。 2 后台支持多平台登陆(比如小程序、h5网页等),不完全依赖小程序SessionKey完成登陆 。 Shiro控制用户权限 1 获取微信小程序code值 2 code值以及appId换取用户openId 3 openId快捷登陆 4 小程序保存登陆Cookie 5 小程序携带Cookie请求后端应用 6 后端根据前端的Cookie校验用户的登陆情况 可惜小程序不支持Cookie,(浏览器一般会保存用户Cookie,方便后续浏览网页使用) 如何解决小程序支持Cookie登陆? 以下是网上常见的Cookie登陆解决方式。
wx.request从res.header['Set-Cookie']中获取cookie信息,并使用wx.setStoargeSync将cookie信息同步写入小程序私有存储空间中
wx.getStorageSync同步将cookie从小程序中取出,小程序携带该cookie请求后台服务,完成用户登陆状态校验。 3、排查过程 问题不可怕,可怕的是不能稳定地复现case。本人平时使用iphone手机,重复用户的操作,基本复现不出来“登陆异常”的现象,只能在服务后台以及小程序前端疯狂埋点打日志。 1)后台日志排查,用户Cookie无效从后台日志可以看出,用户成功登陆,但是用户没有在后续的请求使用用有效cookie去请求后台服务,后台直接拒绝服务。 通过后台和小程序日志发现,出现“登陆异常”的用户基本是安卓用户,苹果用户基本没有这个问题。 3)现象复现,安卓手机提示异常 目标锁定安卓手机,直接找了台安卓手机,重复登陆、预约操作,大概反复操作10次,终于复现了“登陆异常”的现象,喜大普奔啊。 4)微信小程序埋点输出日志,Cookie存取正常 起初怀疑wx.setStoargeSync有bug,未将cookie成功写入小程序。 验证方式:将res.header['Set-Cookie']、wx.getStorageSync日志输出。 如果res.header['Set-Cookie']输出日志为空,则定位是后端服务问题,未将cookie携带返回。 如果res.header['Set-Cookie']输出日志不为空,wx.getStorageSync('cookie')输出日志为空,则定位setStorageSync写入有bug 但是最终现象res.header['Set-Cookie']、wx.getStorageSync('cookie')输出日志均不为空,排查思路中断了。 5)正常与异常Cookie对比,Cookie顺序不对对比正常请求的cookie与异常请求的cookie 发现cookie的顺序不一样 后台shiro做权限控制,返回3个Set-Cookie值,苹果用户的请求基本是以JESSIONID开头,而有问题的安卓用户请求是以remeberMe=Delete开关 6)异常Cookie排查,Cookie拼接不正确 将登陆异常请求的cookie按照正常请求cookie的顺序调整了下, 用户请求后端可以成功登陆。 使用错误顺序cookie请求后端,后端解析cookie并未获取到JESSIONID。 后端是如何解析Cookie,根据分号";"分割Cookie字符串,由于错误顺序Cookie是使用逗号做分割符,后端将Expires与JESSIONID视为一个整体,所以无法解析出JESSIONID 4、为什么苹果手机、部分安卓手机没有问题?没有问题的Cookie,JESSIONID可以被后台正确分割出来。苹果手机获取Set-Cookie顺序是严格一致的,安卓手机Set-Cookie顺序是随机的。 5、问题原因 腾讯小程序Bug,Set-Cookie逗号拼接方式有问题微信开放社区也有人反馈过这个bug,但是以微信社区人员解决问题的稀烂态度,至今未解决该bug。 解决bug只能靠自己去兼容这个bug 6、解决方法 当返回结果的header有多个Set-Cookier时,微信小程序获取res.header['Set-Cookie'],已经是将Set-Cookie用逗号拼接好的字符串。 如果使用简单的逗号分割,Expires时间也含有逗号,Cookie结果是错误的。 Cookie正则分割,分号重新拼接见示例 简单的逗号无法分割,可以使用正则表达式去分割Cookie字符串, 需要被分割的逗号,后继字符串是含有= 7、标准答案 微信小程序使用Cookie登陆标准答案 |