使用 image 发请求的隐患

一般,咱们只会用 img 标签或 Image 对象来加载图片资源,但实际上 Image 也常被用来发请求做数据的上报,一方面缘由就是不须要考虑跨域,并且一般数据上报也不须要处理响应。可是,若是在代码中使用 Image 来发送一些业务请求等,则要考虑其必要性了,若是没有必要,还应该使用 ajax 来发送请求,不然可能埋下一个隐蔽的坑。ajax

背景

最近接手了一个用户反馈的余额没有显示的 bug,因为自身无法在现有信息的条件下复现 bug,又难以从代码中找到逻辑问题(仍是缺乏经验),只能经过打日志的方式找用户配合联调,通过几天的折腾才最终定位到是使用 image 来发请求引发的 bug。那么使用 image 来发请求是如何引发这个 bug 的?存在什么隐患?跨域

排查过程

首先,来看下用户反馈的截图:(其中暗含了一个关键信息)浏览器

登陆态问题bash

经过查看该用户的后台日志信息,发现用户的帐户信息请求的 Cookie 中缺乏了一个关键的票据信息,致使获取不到余额,因而发现获取该票据的请求在日志中并无找到。所以,能够首先判断,是登陆态问题致使用户取不到余额信息,可是,为什么关键的获取票据请求后台没有收到呢?服务器

请求发出了没有?cookie

遇到请求后台没有收到,首先怀疑的是逻辑的问题:应该是存在逻辑漏洞致使在某条件下没有发送该请求。而后经过本地调试以及对该段逻辑的梳理,实际上并没能发现存在请求不被发送的可能。到这一步,就很难走下去了,没有更多的信息,且业务逻辑几乎肯定没有问题。不过,我多少也开始以为奇怪,为啥这里是用 Image 来发送请求:url

var imgReq = document.createElement('img');
imgReq.onload = imgReq.onerror = function () {
	...
}
imgReq.src = url;
复制代码

打更多日志spa

只经过代码,即使能从理论上判断逻辑没有问题,可是没有办法保证运行起来就的确如此。无奈之下,只能在代码中打上更多日志,而后联系用户操做,并将手机上 vconsole 打印的日志发给我(这是十分须要用户配合的 OTZ)。很幸运,用户很配合地按个人指示操做了,我才能拿到用户手机客户端的日志来进行分析。调试

根据日志,我能确定请求必定是发出去了,可是服务器也的确没有收到请求。这让我以为诡异,我开始怀疑是 img.src 这种请求方式的问题了,这才惊悚地发现,**用户的头像没有显示!**这就是那个暗含的关键信息!一开始我觉得用户的头像就是灰色的,因而没有注意,可是在与用户沟通的 QQ 群里,用户是有头像的。不难想到,这极有可能和浏览器无图模式有关。然而,在个人手机上依旧不能复现,因而我只剩这样的假设了:日志

  1. 与手机机型有关;
  2. 与无图模式和 image 请求有关;

带着这样的假设,我增长了 ajax 的请求方式,不得不让用户再试一次,很快就在日志中证明了这个假设:

...
cookie: ...  // 无票据(img 请求以后)
...
cookie: ...  // 有票据(ajax 请求以后)
复制代码

因而我在用户同机型的手机上也复现了这个问题。。。(为何不早点找同机型的手机复现😭 OTZ)

结案

在浏览器无图模式下(这里具体场景为 QQ 浏览器),且在某些机型的手机上,经过 Image 动态发起请求是有可能被拦截的! 上报请求被拦截其实也还能接受(毕竟如今还有多少人在意流量呢),可是业务请求被拦截就可能直接影响功能了。为避免这样的隐患,仍是应该尽可能避免用 Image 来发业务请求。

相关文章
相关标签/搜索