@Lenciel

Tricky Bugs are tricky

最近接连遇到非常tricky的bug。

首先是跟CORS有关的。话说自从google被墙,我们使用了google map或者google font的网站就被客户不停投诉各种打不开。本座只好去找国内可用的CDN,居然发现360的CDN不但有常用的jquery库和fontawsome这些资源,还对google font做了镜像,于是就用了它。

结果用了CDN之后,fontawsome的图标在firefox下显示不正常。curl了一下,发现360的基友们没有正确添加"Access-Control-Allow-Origin"的Header:这就使得像Firefox这样的默认不支持CORS的浏览器拒绝加载不在网站自己域名下的CORS资源。

把fontawsome切换到staticfiles的CDN,问题解决了。

接下来的一个更加tricky,我们的蔡天王在写代码的过程中发现表单被填了怪怪的内容,如下图:

chrome auto fill

他检查了js和html,发现这些值不是我们处理表单的时候填的,WTF?

专治各种疑难杂症的小弟拿到这个bug,首先怀疑的是浏览器那些自动填表的插件,比如LastPass,结果用一个禁用了所有插件的Chrome重现了,WTF?

于是我尝试着把form和里面的input声明成autocomplete="off"的,结果仍然能重现,WTFFFF?

但是试过了几下变换表单里面的项的位置发现bug的行为模式是:

  1. password这个input总是会被用户的密码填写
  2. password上面那个input总是会被用用户的用户名填写(哪怕那个input是别的)

于是就感觉是Chrome的password mananger在干坏事了。google了一下,发现这么个消息

Chrome 34 will now offer to remember and fill password fields in the presence of autocomplete=off.” That means that if a website turns off automatic password collection, Chrome will offer to do it anyway if password manager is enabled.

古德,瓦力瓦力古德。看了如果一个网站你选择了“记住密码”,Chrome的密码管理器就会被这个域名下包含了$('input[name=password]')的表单激活。并且它居然蠢到直接去找password上面一个input来填入用户名,how convenient…

要fix这种行为只能通过在出事的表单里面加上占位用的input来欺骗浏览器。比如我们是在django里面使用django-crispy-form生成表单,就可以重载它的Layout:

1
2
3
4
5
6
7
8
9
self.helper.layout =  Layout(
    HTML('<input style="display:none" type="text" name="fakeusernameremembered"/><input style="display:none" type="password" name="fakepasswordremembered"/>'),
    'name',
    'email',
    'phone',
    'qq',
    InlineCheckboxes('user_permissions'),
    'password', 'confirm_password'
)

更多的相关信息(我希望你知道怎么翻墙),可以看看这里1,或者这里2,或者这里3