在登录页面,输入账号密码,点击提交时,Google浏览器总会自动弹出记住密码的方框,用户点击记住密码或更新密码,重新回到登录页面,输入框会自动回填上次记住的账号密码,鼠标点击输入框,输入框下方会弹出一个用户密码清单。如下图
这本来是Google Chrome浏览器的一项正常功能,为广大用户提供便利。但是,近期做的一个项目中,因系统的特殊性,客户要求,登陆页面不能回填自动账号密码,鼠标点击输入框,也不能出现用户密码清单,更不能在登录后弹出这个Google浏览器记住密码的框。
网上搜索的解决方案,均说将<form> 标签和<input>标签加上属性autocomplete=off ,可是这种解决方案,针对Google浏览器没有任何用处
当时小组第一种解决方案,是将密码输入框 <input type=password> 更改为 <input type=text>,这似乎是一种很好的解决办法,阻止了用户密码自动回填、点击输入框出现用户密码清单、登陆后自动记住密码,但是,此方案,要自己处理密码输入框的明文加密、还要处理中文输入法,因为Google浏览器,无法在input中禁用中文输入法,所以,这个解决方案不够完美,很快被pass掉了
因此我就提出第二种解决方案:
(1)将<input type=password> 添加属性readonly ,进入登录页面时可以阻止用户密码自动回填问题;
(2)重写<input type=password> 的各种监听事件,登录页面代码及说明如下,
<script src="js/jquery-3.4.1.min.js"></script>
<form autocomplete="off" action="home.jsp" method="POST">
<label id="ALabel">用户名:<input type="text" name="username" autocomplete="off"/></label>
<label id="BLabel">密码:<input type="password" name="password" autocomplete="off" style="ime-mode:disabled" readonly/></label>
<label id="CLabel"><input type="submit" autocomplete="off" style="ime-mode:disabled" readonly/></label>
</form>
<script>
$(function () {
var ps = $("input[type=password]");
ps.click(function (e) {
//为什么先失去焦点,在获取焦点,这样子可以避免第二次或更多次连续点击输入框时,出现的用户密码清单的框可以快速去除
ps.blur();
ps.focus();
});
ps.focus(function (e) {
//使用setTimeout 包住,告诉JS是异步执行,这样子,就可以阻止第一次点击获取焦点时,下拉用户密码清单的框的出现
setTimeout(function () {
ps.removeAttr("readonly");
//获取焦点时 同时去除只读,这样可以获取光标,进行输入
})
});
ps.blur(function (e) {
//失去焦点立马更新为只读
ps.attr("readonly","readonly");
});
// 监听键盘输入事件
// 当keyCode=8(backspace键) 和 keyCode=46(delete键)按下的时候,判断只剩下最后一个字符的时候阻止按键默认事件,自己清空输入框
// 当keyCode=8(backspace键) 和 keyCode=46(delete键)按下的时候,判断如果处于全选状态,就阻止按键默认事件,自己清空输入框
// 这种用来避免删除最后一个字符完后出现下拉用户密码清单的框
ps.keydown(function (e) {
var keyCode = e.keyCode;
if (keyCode === 8 || keyCode === 46) {
//backspace 和delete
var len = ps.val().length;
if (len === 1) {
ps.val("");
return false;
}
if (e.target.selectionStart === 0 && e.target.selectionEnd === len) {
ps.val("");
return false;
}
}
return true;
});
});
</script>
这种方案,第一次点击密码框,不会出现下拉用户密码清单,但是,第二次点击的时候,那个用户密码清单的框会一闪而过,这个也是一种不好的体验。
因此增加一种监听事件,代码及说明如下,
//用来阻止第二次或更多次点击密码输入框时下拉用户密码清单的框一闪而过的问题
ps.mousedown(function () {
ps.blur();
ps.focus();
});
到此为止,登录页面的用户密码回填问题、点击用户或密码框会出现下拉用户密码清单的框的问题已经完美解决了。
(3)解决登录后自动弹出记住密码那个框的问题,这边就比较头疼了,因为,只要登录页面存在<input type=password>这个控件,不管是表单提交,或者手动跳转页面,只要页面变动,就一定会弹出这个框。
但是,只有一种情况,我觉得很奇怪,因为,表单提交后重定向页面仍然为当前登录页面时,竟然没有弹出记住密码的框。这个让我很高兴,因为,有一种情况让他不弹,这其中肯定有他的奥妙所在。我大胆猜测,是因为,当前页面有这个密码输入框<input type=password>存在,所以,才没有弹出那个记住密码的框。
于是,我在登录成功的页面也加入如下代码:
<input type="text" name="username" autocomplete="off"/>
<input type="password" name="password" autocomplete="off" readonly/>
神奇了,真的不会弹了
但是,两个输入框放在那里,肯定不行,我首先想到的就是给这两个input 加上属性style="display:none",登录成功的页面的输入框不见了,但是,记住密码的框又开始弹出了,我想,input 不能隐藏,于是我使用div 包起来,如下:
<div style="display:none;">
<input type="text" name="username" autocomplete="off"/>
<input type="password" name="password" autocomplete="off" readonly/>
</div>
但是也不行,说明,input 不能被隐藏,只要被隐藏,浏览器就识别不到他了。
好了,这个难不倒我,修改代码如下
<div style="display:block;opacity: 0;width:0px;height:0px;overflow: hidden">
<input type="text" name="username" autocomplete="off"/>
<input type="password" name="password" autocomplete="off" readonly/>
</div>
这样子,没有隐藏input,也没隐藏外层div,只不过将div 的长宽都设置为0,透明度设置为0,里面内容超出div部分不挤出外层,这样子就伪造了input 的不可见,就不影响登陆成功的页面布局,也成功阻止了chrome浏览器记住密码框的弹出,完美👍👍👍
问题对于我们整个小组来说,的确很难,没有遇到过此类问题,网上资料有限,不完整,整个小组没人懂得有效的解决方案,所有人几乎已经放弃了。但是,我,撇开网上的所有资料,从0开始研究,自己写简单DEMO,一步一步探索浏览器的奥秘,最终,解决方案,就是这么简单~
码哥zhenyu5665:赞!这个方法对于chrome,IE,360都可以,但是火狐就不行了,还是会出弹窗询问是否记录密码4天前
看到这位兄弟留言提到火狐浏览器兼容问题,其实,我们系统环境限制,当时只为chrome 考虑,不过刚好有空就研究了下,火狐浏览器,可以设置隐藏的表单,输入仍旧使用原来的表单,但通过这个表单进行提交登录,但是在提交请求前,需要手动重置一下原表单的DOM,然后进行提交。登录页面代码更新如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录页面</title>
<script src="js/jquery-3.4.1.min.js"></script>
</head>
<body>
<div id="bodyDiv">
<form id="loginForm" autocomplete="off" >
<label id="ALabel">用户名:<input id="inputUserName" type="text" name="username" autocomplete="off"/></label>
<label id="BLabel">密码:<input id="inputPassword" type="password" name="password" autocomplete="off" style="ime-mode:disabled" readonly/></label>
<label id="CLabel"><input id="submitButton" type="button" value="提交"/></label>
</form>
</div>
<div style="display: none">
<form id="realSubmitForm" action="home.jsp" method="POST">
<input type="text" name="username" id="realUserName">
<input type="text" name="password" id="realPassword">
</form>
</div>
<script>
$(function () {
$("#submitButton").click(function () {
$("#realUserName").val($("#inputUserName").val());
$("#realPassword").val($("#inputPassword").val());
var html = $("#bodyDiv").html();
$("#bodyDiv").html("");
$("#bodyDiv").html(html);
//initLoginFormListener();
$("#realSubmitForm").submit();
});
initLoginFormListener();
});
function initLoginFormListener() {
var ps = $("input[type=password]");
ps.click(function (e) {
//为什么先失去焦点,在获取焦点,这样子可以避免第二次或更多次连续点击输入框时,出现的用户密码清单的框可以快速去除
ps.blur();
ps.focus();
});
ps.focus(function (e) {
//使用setTimeout 包住,告诉JS是异步执行,这样子,就可以阻止第一次点击获取焦点时,下拉用户密码清单的框的出现
setTimeout(function () {
ps.removeAttr("readonly");
//获取焦点时 同时去除只读,这样可以获取光标,进行输入
})
});
ps.blur(function (e) {
//失去焦点立马更新为只读
ps.attr("readonly","readonly");
});
// 监听键盘输入事件
// 当keyCode=8(backspace键) 和 keyCode=46(delete键)按下的时候,判断只剩下最后一个字符的时候阻止按键默认事件,自己清空输入框
// 当keyCode=8(backspace键) 和 keyCode=46(delete键)按下的时候,判断如果处于全选状态,就阻止按键默认事件,自己清空输入框
// 这种用来避免删除最后一个字符完后出现下拉用户密码清单的框
ps.keydown(function (e) {
var keyCode = e.keyCode;
if (keyCode === 8 || keyCode === 46) {
//backspace 和delete
var len = ps.val().length;
if (len === 1) {
ps.val("");
return false;
}
if (e.target.selectionStart === 0 && e.target.selectionEnd === len) {
ps.val("");
return false;
}
}
return true;
});
//用来阻止第二次或更多次点击密码输入框时下拉用户密码清单的框一闪而过的问题
ps.mousedown(function () {
ps.blur();
ps.focus();
});
}
</script>
</body>
</html>
-----------------------------------------解决问题,要先懂问题,懂他的原理,才能知道如何解决----------------------------------------