目录
写在前面: 如有转载,务必注明出处,否则后果自负。
1.要解决的问题
最近工作上遇到一个客户反馈的问题,说是网页上的登录界面会出现自动填充账号和密码,这会导致系统不安全,账号泄露等风险。我寻思着ntm要是没有在浏览器上点击自动保存账号和密码它会自动填充吗?真是无语。本以为不需要修改,让他自己在浏览器上清除保存密码的记录即可,没办法,打工人作为牛马有求必应。
所以,我们要解决的就是,把浏览器对input的自动填充以及填充提示给Ban掉。如下图的三个区域。
由于不同的浏览器对于自动填充有着不同的策略,所以我们需要使出各种招式组合在一起才能把它消灭,在这里我主要使用谷歌、火狐、Edge(原IE)三大浏览器来对比查看效果,一起来看看吧!
简单写了一个Demo,来模拟表单登录:
html
<!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>
css
/* 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"。
html
<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框设置为不可见,从而瞒天过海。
html
<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
/* 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事件,实现偷梁换柱,功德圆满!哈哈哈哈哈...
html
<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的值进行传递。
具体代码:
html
<!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