本节书摘来自华章计算机《Web测试囧事》一书中的第1章,第1.4节,作者 黄勇 雷辉 徐潇 杨雪敏,更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1.4 利用JavaScript加载的漏洞提前购买抢购商品
自从小米手机推出以来,抢购风潮在各类网站上盛行起来,小蔡测试的网站自然也不能免俗,项目组开发的网站也包含了抢购功能。
对于抢购来说,只有到了特定的时间后,商品才会开放并允许抢购,并且抢购网页的代码里使用的时间会定期和服务器进行同步。
小蔡设计了丰富和全面的测试用例,在执行基础测试用例过程中没有发现抢购功能的Bug,不过在进行多地区和多语言的性能测试时,她发现了一个功能上的漏洞,发现漏洞的过程是这样的。
在执行性能测试时,需要选取不同国家和地区的服务器去模拟用户的真实访问,以验证产品性能是否能满足用户体验的要求。显然,通过这些不同国家和地区的服务器访问网站,会比小蔡在公司内部使用内网访问速度慢,更别提有些国家和地区网络发展慢,这些区域的访问速度就更慢了。
然而正是通过使用这些网速很慢的服务器,小蔡发现了这个功能上的漏洞。
1)在高速或者说正常网速的情况下,当用户打开抢购商品的页面时,页面JavaScript会很快加载并执行完成,这时“加入购物车”的按钮会变灰,无法进行操作(见图1-5)。
2)而当网速很慢时,由于网页中JavaScript是顺序加载执行的,所以“加入购物车”按钮先会显示为可以操作的状态,等JavaScript加载完成后,才会变灰,不可操作(见图1-6)。
3)所以在慢速网络中,当页面JavaScript没有加载完成时,用户会看到“加入购物车”按钮是可用状态,因此用户可以点击该按钮,并把抢购商品加入购物车,于是用户就可以在正式抢购开始之前顺利地抢到该商品了。实际上甚至在商品无货的情况下,用户也可以在JavaScript没有加载完时点击“加入购物车”按钮,并且成功把无货商品加入购物车 (见图1-7和图1-8)。
这个问题是由JavaScript没有加载完成引起的,但是稍懂技术的人甚至可以禁用浏览器的JavaScript,或者通过查看网络访问的URL后,在按钮是灰色的状态下也有可能提交购买请求。所以,修改这个Bug时,还需要在提交订单时做二次验证,去验证该商品是否有货,或者是否已经处于抢购状态,当状态为“是”的时候,才允许后续操作。
当小蔡把这个问题提交给开发人员和产品经理后,经过大家的讨论,发现如果调整商品页面上的JavaScript加载顺序,会涉及很多JavaScript文件的修改,影响范围会很广,包括移动页面上的代码也需要大幅修正,因此整体工作量比较大。鉴于刚才提到的在提交订单时做二次验证也能避免这样的问题,所以他们一致决定采取做二次验证这种方案来进行修复。
(1)加载
不管是script标签直接引入的情况,还是src加载的外部资源,都会阻塞页面的渲染。所以一般为了从体验上考虑,我们会将JS文件放置在body标签闭合之前。不过新版的IE、Firefox、Safari和Chrome都允许并行下载JavaScript文件。但是只是JavaScript文件可以并行下载,渲染还是被阻塞的,页面仍然必须等待所有JavaScript代码下载并执行完成才能继续。
(2)执行
每当JavaScript文件加载完成后,都会立刻执行该文件。所以你会看到下一次的请求并不是在上一次请求结束之后立即开始,中间的耗时就是上一个脚本文件的执行时间。
一般对于JavaScript的优化建议如下。
1)将script脚本文件放置在body标签闭合之前。
2)减少script请求数量。
3)无阻塞脚本,在页面加载完成后才加载JavaScript代码。这就意味着在window对象的onload事件触发后再下载脚本。
不过在上面这个故事中,正是由于对JavaScript的优化引发了抢购页面先显示元素可操作,然后在JavaScript加载完成后,JavaScript执行使元素不可操作。