某一天测试提了一个bug,系统进入到某个页面中后,出现登录失效,不管怎么样,只要进入这个页面再点击其他链接就会去到登录页面,测试环境没有问题。
因为测试环境没有任何问题,所以怀疑是代码本身的问题,于是在本地测试,发现本地没有问题,于是重新打包部署到正式服务器测试,发现还是出现异常。
因为代码和测试环境与本地都是一样的,所以怀疑是数据原因导致登录失效,所以在本地将配置切换到正式环境,发现本地还是没有任何问题,排除这一问题,同时后台也没有任何异常产生,最终追踪到页面,发现页面发出的ajax请求的JSESSIONID 发生了改变,于是开始排查JSESSIONID 为什么会改变,百度到了2种原因:
首先第一个,如果是因为调用reset方法导致登录失效,那么所有的环境理论上都会登录失效,但是为了保险起见,还是检查一下,最后发现并没有地方调用reset方法,所以排除此项。于是检查第二个,但是整个系统并没有跨域,但是为了保险,还是将网上说的方法在ajax请求中添加
beforeSend: function(xhr) { xhr.withCredentials = true; } crossDomain:true,
加上之后发现还是不行,于是以上2种原因被排除
由于搜索到的原因都没能解决,所以只能自己推测具体原因了,因为以上2种已经排除,所以推测可能是因为js清空了cookie,毕竟JSESSIONID是保存在cookie里面的,如果调用js清空了cookie也会导致登录失效,于是在jsp页面中先注释所有js,然后写一个简单的ajax请求,判断JSESSIONID是否改变,测试结果JSESSIONID还是发生了改变,所以也不是js清空了cookie的问题。
事情到了这里,这个bug已经非常诡异了,但是诡异也要解决,于是继续推测:是否是进入页面的时候登录已经失效了,所以新建了一个空的jsp页面,写了一个ajax请求,判断JSESSIONID是否改变,结果发现JSESSIONID没有改变,得出结论:JSESSIONID是在以前的jsp页面中发生的改变,但是不是js导致的,所以开始怀疑HTML,但是HTML理论上不会导致登录失效,所以怀疑是jstl标签导致的登录失效,于是挨个删除jstl标签和表达式,最后发现是输出一个空对象的问题,但是奇怪的时候其他地方输出都没有问题,就那行出了问题,而且测试环境和本地都是空的也没有任何问题,但是的确去掉后就不会出现登录失效的问题了
判断是否为空来进行jstl标签输出后没有问题了,但是本身问题也够奇怪,应该其他地方也没有判断而直接输出的,就不会有问题,偏偏这里有问题,而且也不是说抛出什么异常,而是让登录失效了,因为异常诡异,所以记录下来,另外因为jstl输出空对象不会有问题,所以有时候一旦出问题了就是莫名其妙的问题,看来还是最好选择freemarker这种带强制性的模板引擎比较好,虽然有null就会异常,但是至少会加强非空判断,而且freemaker也可以生成HTML,来加速响应速度