一、前言
今天要介绍的命名冲突并不是系统内部的命名冲突,而是系统与浏览器插件之间的命名冲突。
二、现象描述:
通过查看运维同事上传到工单中的图片可得出这样的结论:用户页面无法加载JS、CSS,但是HTML可以成功解析。
三、故障分析过程,试图重现故障:
(1)、由于HTML可以成功解析,排除网络原因。
(2)、查资源服务器的ngnix访问日志,只有页面请求却没有JS、CSS的请求。猜测页面在请求加载静态资源的过程中出了问题。
(3)、可是邮箱加载静态资源都是使用统一的方法:loadScript、loadCss。如果出问题应该是所有用户都有问题,而不是部分用户。而且如果这两个方法有问题很容易就被测试同事发现,不可能带上生成线。
(4)、开始怀疑出问题的用户浏览器被挂马了。邮箱的页面被注入了恶意代码,导致静态资源加载失败。
四、登录用户电脑,验证故障分析过程:
(1)、安装抓包工具:HttpWatch。注意,这种情况Fiddler并不适用,因为Fiddler依赖.net framework框架,用户很可能没有安装。
(2)、注意用户有可能没有安装解压软件,所以如果需要向用户电脑安装软件的话,最好打包成zip格式。
(3)、登录邮箱,查看静态资源的请求过程。发现请求的地址不正确。查看源码,发现loadScript函数并没有异常。
(4)、在用户浏览器地址栏运行:javascript:alert(loadScript.toString());void(0); 发现弹出来的方法根本不是我们定义的方法。可以下结论:用户浏览器被注入了代码,并且执行优先级要高于我们自己定义的函数。
五、找出恶意插件:
(1)、打开用户浏览器的插件管理界面,用户通常都是IE浏览器,打开管理加载项界面:
(2)、依次禁用加载项,刷新页面,重新在用户浏览器地址栏运行:javascript:alert(loadScript.toString());void(0); 如果禁用某一加载项后可以输出我们自己脚本,就代表这个插件有问题。
(3)、最终定位出问题:用户安装了快播浏览器插件,该插件在浏览器侧注入了命名毫无特点的函数:loadScript
六、规避措施:
编码过程中不得已需要定义全局函数时,命名务必携带产品特性。避免被其他产品的浏览器插件覆盖。
七、结束语:
其实快播注入的并非是恶意代码,造成故障的根本原因其实是命名冲突。Martin Fowler在《重构:改善既有代码的设计》中专门介绍过函数的命名。感兴趣的同学可以翻阅这本书。绝对值得拥有。