目录
- 1.要解决的问题
- 2.一技能:原生属性,小试牛刀
- 3.二技能:傀儡input,瞒天过海
- 4.三技能:JavaScript出击,直接开大
- 5.九九八十一难,永远还有最后一难
写在前面: 如有转载,务必注明出处,否则后果自负。
1.要解决的问题
最近工作上遇到一个客户反馈的问题,说是网页上的登录界面会出现自动填充账号和密码,这会导致系统不安全,账号泄露等风险。我寻思着ntm要是没有在浏览器上点击自动保存账号和密码它会自动填充吗?真是无语。本以为不需要修改,让他自己在浏览器上清除保存密码的记录即可,没办法,打工人作为牛马有求必应。
所以,我们要解决的就是,把浏览器对input的自动填充以及填充提示给Ban掉。如下图的三个区域。
由于不同的浏览器对于自动填充有着不同的策略,所以我们需要使出各种招式组合在一起才能把它消灭,在这里我主要使用谷歌、火狐、Edge(原IE)三大浏览器来对比查看效果,一起来看看吧!
简单写了一个Demo,来模拟表单登录:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>input禁止自动填充</title><link rel="stylesheet" href="./index.css">
</head><body><form action="/"><input id="userName" type="text" placeholder="请输入账号" ><input id="userPwd" type="password" placeholder="请输入密码" ><button type="submit">提交</button></form>
</body></html>
/* index.css */
* {margin: 0;padding: 0;box-sizing: border-box;
}form {width: 300px;height: 200px;margin: 100px auto;
}input {width: 100%;height: 40px;padding: 0 10px;margin-bottom: 20px;border: 1px solid #ccc;border-radius: 5px;outline: none;
}button {width: 100%;height: 40px;border: 1px solid #ccc;border-radius: 5px;background-color: aquamarine;
}
2.一技能:原生属性,小试牛刀
给input 添加原生属性autocomplete:
对于text框,添加 autocomplete=“off”;
对于password框,添加 autocomplete=“new-password”。
<input id="userName" type="text" placeholder="请输入账号" autocomplete="off">
<input id="userPwd" type="password" placeholder="请输入密码" autocomplete="new-password">
谷歌浏览器:仅对 type=‘text’ 的input有效,即不能自动填充,也不会显示填充提示;而对于密码框 type=‘password’,虽然不会自动填充,但密码框聚焦后会出现填充提示,点击填充提示的账号密码,可以实现自动填充。如图所示:
火狐浏览器:输入框和密码框都不会出现自动填充,但二者聚焦后都会出现填充提示,并都能进行点击后填充。如图所示:
Edge浏览器: autocomplete对该浏览器完全无效。初始化页面即会自动填充账号和密码。
3.二技能:傀儡input,瞒天过海
给text框和password框前后各加一个假的input框,让浏览器的自动填充对假的input框生效,然后用css把假的input框设置为不可见,从而瞒天过海。
<form action="/"><input id="fakerUserName1" type="text" placeholder="请输入账号" autocomplete="off"><input id="userName" type="text" placeholder="请输入账号" autocomplete="off"><input id="fakerUserName2" type="text" placeholder="请输入账号" autocomplete="off"><input id="fakerUserPwd1" type="password" placeholder="请输入密码" autocomplete="new-password"><input id="userPwd" type="password" placeholder="请输入密码" autocomplete="new-password"><input id="fakerUserPwd2" type="password" placeholder="请输入密码" autocomplete="new-password"><button type="submit">提交</button>
</form>
/* css将假的input设置为不可见 */
input#fakerUserName1,
input#fakerUserName2,
input#fakerUserPwd1,
input#fakerUserPwd2 {position: fixed;top: -100%;left: -100%;
}
谷歌浏览器: 该技能对谷歌的效果与属性autocomplete的效果一样,故与技能一相比无任何变化。即text框既不能填充也无填充提示,password框不能填充但聚焦后有填充提示,并且点击后可自动填充。
火狐浏览器: 该技能对text框有效,既不能自动填充,也不会出现填充提示,对password无效,不能自动填充,但聚焦后有填充提示,点击后可自动填充。如图:
Edge浏览器: 解决了初始化页面即自动填充的问题,对于text框既不能自动填充,也不会出现填充提示,对于password框,不能自动填充,但聚焦后有填充提示,点击后可自动填充。如图:
注意: 添加假的input框时要注意给input的id也要加上,否则可能不起作用,因为不同的浏览器对此有不同的策略,有时,id的字符长短也会产生不同的效果,可自行尝试。
4.三技能:JavaScript出击,直接开大
通过前两个技能,可以发现,这些浏览器的策略是非常激进的,尤其是对于password框。有时无论你添加多少个假的input框,可能对于浏览器而言,它并不在乎,因为只要是 type=‘password’ 的input框,它就会在聚焦后出现填充提示,点击这个填充提示,就又可以实现自动填充。对于某些用户而言,可能由于不小心点击了在浏览器上自动的保存密码,但对于该功能,其账号的安全性便大大降低了,尤其对于某些注重隐私的公司而言,这可能是不可接受的,因为,商战是处处皆有可能的,于是乎,一口大黑锅就甩到了开发人员的身上。
既然如此,开发狗该怎么办呢?
既然技能一和技能二只对 type=‘text’ 的input框有效,那我就不要使用 type=‘password’ 了呗。
嗯!真是大聪明?!
如果这样的话,输入密码的时候不就直接明文输入了吗?
对啊…
滚…
等等,你说什么?
滚…
上一句,输入密码的时候?输入密码的时候??输入密码 的时候 !!!
OK,JavaScript出击!
于是乎,办法出现了,我们可以将 type=‘password’ 改为 type=‘text’ ,然后使用JavaScript监听input事件,实现偷梁换柱,功德圆满!哈哈哈哈哈…
<body><form action="/"><input id="fakerUserName1" type="text" placeholder="请输入账号" autocomplete="off"><input id="userName" type="text" placeholder="请输入账号" autocomplete="off"><input id="fakerUserName2" type="text" placeholder="请输入账号" autocomplete="off"><input id="fakerUserPwd1" type="text" placeholder="请输入密码" autocomplete="new-password"><input id="userPwd" type="text" placeholder="请输入密码" autocomplete="new-password"><input id="fakerUserPwd2" type="text" placeholder="请输入密码" autocomplete="new-password"><button type="submit">提交</button></form><script>document.querySelector('#userPwd').addEventListener('input', function () {this.type = 'password';})</script>
</body>
看看效果:
谷歌:
火狐:
Edge:
5.九九八十一难,永远还有最后一难
根据网友反馈,当输入密码然后清空之后会出现自动填充的提示,我试了下,确实如此。而且谷歌和Edge出现这种情况之后还会影响type='text’的输入框也出现自动填充。
只能说浏览器对于自动填充的策略确实很激进啊,但凡出现password,它似乎就对这个input进行了跟踪,无论type再怎么变,它也会给你弹出自动填充。
这里的解决办法是使用账号脱敏的思想,坚决不使用password密码框,关于账号脱敏可以看看我的下一篇文章,文章地址在本文末尾。
具体思路就是使用text框输入密码,输入时用•代替明文显示,然后用一个辅助input记录真实密码,传递数据时就使用这个辅助input的值进行传递。
具体代码:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>* {margin: 0;padding: 0;box-sizing: border-box;}.container {width: 300px;padding: 50px 20px;margin: 100px auto;border-radius: 5px;background: #ccc;}input {width: 100%;height: 40px;padding: 0 10px;margin-bottom: 20px;outline: none;border: 1px solid #ccc;}input#realUserPwd {display: none;}button {width: 100%;height: 40px;cursor: pointer;outline: none;border: 1px solid #ccc;background-color: #fff;}</style>
</head><body><form class="container" action="/"><input type="text" id="userName" placeholder="请输入账号" autocomplete="off"><input type="text" id="userPwd" placeholder="请输入密码" autocomplete="off"><input type="text" id="realUserPwd" autocomplete="off"><button type="submit">提交</button></form><script>const inputField = document.querySelector('#userPwd');const realUserPwd = document.querySelector('#realUserPwd');inputField.addEventListener('input', function (e) {// 获取输入框中的值const inputValue = this.value.trim();// 拼接每一次输入的当前数字realUserPwd.value += inputValue.substring(inputValue.length - 1);// 防止用户删除上一个输入值时出现错误// 并且// 防止用户通过粘贴输入值时只监听到最后一位数而出现的错误if (inputValue.length != realUserPwd.value.length) {realUserPwd.value = inputValue;}// 将明文替换成•显示this.value = inputValue.substring(0, inputValue.length).replace(/./g, '•');console.log('res', this.value, this.value.length, realUserPwd.value, realUserPwd.value.length);})</script>
</body></html>
看看效果:
谷歌浏览器:
火狐浏览器:
Edge浏览器:
看起来已经解决了这个bug,并且代码也精简了很多,如果还有其他问题,欢迎交流!
后记:
对于浏览器版本的不同可能有些许差异,但问题不大。对于我使用的浏览器的版本,见下图:
SOS: 但与客户的战争还未结束,还是与input有关,也就是输入账号脱敏的问题,也就是实现下图的效果,切莫大意,我刚开始确实低估了它,不过最终也是如愿解决。
欲知后事如何,且听下回分解。
对input输入框脱敏的实现(input输入时可回删、可粘贴)可查看文章:https://blog.csdn.net/qq_51667621/article/details/139988001