日常玄学记录。目前我从事Java后端开发的工作,与移动App开发者对接API接口,App上线后发现有些机型无法正常登陆,为了排查问题使用了不同的模拟器安装App并且进行抓包分析,最终找到了问题所在,在此记录。
具体问题描述
最近上线的一个项目,Android客户端采用原生和非原生混合开发,后端API采用Session机制认证,出现部分Android机型无法使用WebView中加载的核心业务,通过抓包发现,某些客户端在使用WebView发起请求时没有带上登录时得到的SESSIONID,Android开发人员通过日志输出证实有把登录的SESSIONID同步设置给WebView的Cookie,并且通过cookieManager.getCookie方法能够取到同步设置的Cookie。于是我只能自己再进一步验证一下,最终找到问题所在。
测试发现主要问题
1.部分Android机型(部分厂商的7.x和8x的Android版本号)无法请求到Web页面,会被后端拦截
2.我用Android 5.x 到 9.x 的模拟器测试完全正常,抓包时请求头的Cookie中也正常携带SESSIONID,但是用户真实机型出现不携带Cookie的情况
3.Android开发人员确实把SESSIONID同步设置给WebView的Cookie了,客户端设置的Cookie也可以通过getCookie方法取出来,但是抓包发现在某些机型上WebView加载URL的时候请求头中并没有带上Cookie。
解决过程
大学研究了3年Android,也遇到过各种坑,这次问题我的第一反应就是不同机型的差异性导致的。回想了一下之前Android开发中曾经遇到的坑,于是用Android4.3版本的模拟测试了一下,发现请求头中果然也没带上Cookie
android4.3WebView加载接口地址时,请求头数据包如下图所示:
用android5.0版本的模拟器测试了一下,发现请求头中有携带Cookie

所以,这些机型的产商可能要摸一下自己的良心了,为了减少ROM的开发成本,是不是把部分低版本的WebKit内核直接照搬编译到新系统里了?
在网上经常可以看到一堆相互抄袭的文章,WebView同步Cookie的方法如下:
1 | /** |
这段代码乍一看没什么问题,虽然getCookie可以取到设置进去的Cookie,但是请求时存在没带上Cookie的情况。
问题就出在同步方法上。如果刚好看过4.x的源码,会发现和现在的版本有比较大的不一样。
这里最大的区别是:
4.3版本的removeSessionCookie方法删除Cookie是异步的
sync同步设置Cookie也是异步的。
也就是说他可能在你设置了Cookie之后才执行remove操作,或者在WebView请求后才设置Cookie,
WebView发起请求时要么Cookie还没被设置,要么就是已经被删除。
所以在WebView加载URL发起请求时根本没有把Cookie带上。
一、Android5.0及以上的WebView操作Cookie后的时序图
二、Android4.3版本)操作Cookie后的时序图
解决方案
- WebView使用Post请求就可以在头部带上自定义参数,需要后端接口也跟着一起改
- Android客户端删除Cookie操作后面加上等待时间比如 Sleep 1000L。
- 上面这两种方案只是解决问题,但是并不是规范的,其实CookieSyncManager类和cookieManager的很多方法已经被标注为弃用
https://developer.android.com/reference/android/webkit/CookieSyncManager通过android官方文档可知,这些都被标注了@Deprecated,所以开发者在开发的时候要考虑兼容性问题,针对大众的产品要足够的细心
出现这些BUG的主要原因
在我写这篇文章时,Google官方虽然以及将Android更新到了9.0的版本,但是目前在中国市场还存在很多版本碎片化的问题,
网上有很多过时的API示例,国内的很多文章都相互抄袭,有的根本没有自己试验过就拷贝过来发表,这样的传播是非常不负责任的。
另外还有一个主要因素是很多厂商喜欢自己定制,曾经我还在开发Android应用时,就遇到某个厂商把摄像头拍照回调的API修改了,导致横竖屏切换的的问题,这种定制可以说是非常恶心来形容了,可能这也是我弃坑的原因之一吧。另外我真的非常喜欢写后台,所以现在能够写API接口感到很欣慰。
曾几何时,依稀记得在学校工作室的时光,曾经的方老师跟我们说过这样一句话“遇到问题不要说我是学Android的,后端的我不管…,不要说什么从Android开发转后端开发这样的话,你曾经学到的知识就是你自己的,没有转行,都是开发,能在一个领域有所成就取决于你有多专注”。原话虽然记得不是很清楚,但是大体就是这个意思,这句话到现在一直铭记在我脑海里。所以遇到问题我不怕,我的想法只有一个:找出问题,并解决它。