浏览器的代填功能设计,是为了方便用户登录,但同时也存在安全隐患,方便了用户自己也方便了他人,相关账号信息轻易就可以被他人利用登录了,
为了个人账号安全,一是用户自身不要保存账号密码到浏览器,二是网站方要做页面处理,防止浏览器做这样的代填操作。
应用场景
在一些公用的电脑上如会议室、教学室、图书馆、网吧等,你用浏览器访问了一些常用站点,在登录的时候浏览器一般会提示你,是否要保存密码,然后你不小心保存了账号密码,如下:

别人再用此电脑访问相同站点的时候,就很容易发现浏览器保存的历史账号,一种是自动代填,访问该页面就默认填好了一个用户名和密码(如图1),一种是手动代填,清空输入框后,会回显保存的历史账号列表(如图2),供用户选择登录。


这种浏览器的代填功能设计,是为了方便用户登录,但同时也存在安全隐患,方便了用户自己也方便了他人,相关账号信息轻易就可以被他人利用登录了,
为了个人账号安全,一是用户自身不要保存账号密码到浏览器,二是网站方要做页面处理,防止浏览器做这样的代填操作。
作为网站方,页面处理该如何做呢
首先屏蔽自动代填,登录和密码框不要自动代填已经保存过的密码和历史输入,常用的方法是在输入框加个autocomplete属性并置为off

此种方式只能在谷歌和火狐浏览器中生效,而对于已保存的账号信息即手动代填的屏蔽,在浏览器中却是不起作用,如图所示:

点击用户名输入框就会回显提示,后来经过反复调试,发现输入框是文本和password类型组合就会触发浏览器的自动回显,网上也给过在输入框上加上onfocus事件来更改输入框类型的方案:

但逻辑还是不够严密,我输错了密码再回删,它又会回显出来,因为此时onfocus事件已生效,将文本框类型置为password,同时表单提交后刷新也会:

网上溜达了一圈,还是没有一个明明白白的答案,最后经过不断尝试,给出的解决方案如下:

代码中为什么要监听keyup事件呢,经测试keypress和KeyDown是监听不到按键backspace回删事件的,只好通过keyup事件动态的判断密码框值的长度来设置它的类型。
完成以上操作后,此时还是会遗留一个问题:

动态改变输入框的type在IE8下是不行的,因为IE8里面input的type是只读的,此时在IE8中,密码框输入时会明文显示,“如果你的项目中需要 IE 多个版本的兼容性的话,这种方案只好放弃…”嗯,这句话是别人说的,当然放弃,是不可能的,那句话咋说的,“只要思想不滑坡,方法总比困难多”。
继续探索兼容IE8的办法:
在密码输入框input外加上一层div,当输入的值发生变化重写input的html,如:

当这样处理后,会发现输入框得不到焦点(即看不到输入中闪烁的光标),因为Input框已经被替换掉了,上次的输入状态自然就看不到了,怎么办呢

一般的解决方案是重新获取该输入框节点,然后执行onfoucus事件,让其重新获得焦点,但这样做会有一个弊端,每次随着输入值变化,输入框替换后都得重新获取一次,dom性能开销大,作为一个专业的程序员,一定不能这样干。
我想到的是能不能将输入框的焦点事件进行转移,类似委托的机制,让它的父级元素来干这个事。Input框的父级元素是div标签不支持focus/blur事件,于是在外层div上加了tabindex属性,对于div/span等其他元素需要设置tabindex才能获取到焦点,于是我们就把输入框的焦点转移到了外层div上,而实际效果还是在输入框中。

同时我们也可以把密码输入框的keyup事件委托给外层div,这样在非IE和其他浏览器的情况下,都只需监听外层div的keyup事件做统一处理了,于是封装函数为

封装好函数后,就可以页面刷新和事件绑定的时候单独调用了

小结:
解决问题的过程中总是曲折的,问题有时一个接着一个,虽然我们不能像灭霸一样打个响指就能解决,但一定要本着把这件事做好的初心,不断尝试和改进,“曲径通幽处,禅房花木深”,每一个问题都将是我们成长的契机。