目录
- 1.要解决的问题
- 2.第一回合:substring + replace
- 3.第二回合:移魂大法
- 4.第三回合:移花接木
- 5.第四回合:万佛归宗
写在前面: 如有转载,务必注明出处,否则后果自负。
1.要解决的问题
继续与客户battle,啊不,与input输入框battle!
扶我起来,我还能战。。。
那厮继续以安全性和隐私性为由,说由于登录界面的账号是以身份证号进行登录的,而在输入身份证号时如果全部暴露出来,那是及其不安全的,所以需要隐藏从第11位开始到结尾的数字,如下图:
首先,快速写一个Demo测试一下:
<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;
outline: none;
border: 1px solid #ccc;
}
</style>
<div class="container">
<input type="text" id="userName" placeholder="请输入身份证号">
</div>
2.第一回合:substring + replace
可以很自然的想到,使用input监听事件,然后通过substring和replace实现截取和替换。
const inputField = document.querySelector('#userName');
inputField.addEventListener('input', function (e) {
const inputValue = this.value.trim(); // 获取输入框中的值
// 判断输入长度是否超过十位数
if (inputValue.length > 10) {
// 取前十位可见
const visiblePart = inputValue.substring(0, 10);
// 第十位后面的数字用*替换
const hiddenPart = inputValue.substring(0, inputValue.length - 10).replace(/./g, '*');
// 组合成脱敏后的值
const maskedValue = visiblePart + hiddenPart;
// 更新输入框中的显示值
this.value = maskedValue;
}
console.log('res', this.value);
})
问题来了: 替换之后,身份证的后12位数字就全部变成了 * 号 ,我们知道,账号密码进行登录时,要把数据传到后端,可是如果使用这个结果传到后端,肯定是登录失败的,因为后端无法识别这个*原来到底是什么数字。
3.第二回合:移魂大法
首先想到,可以使用一个变量realValue记录完整的真实的账号,传递数据给后端时就使用该变量的值进行传递;还要使用变量temp来记录每次输入时当前位数要替换成*的数字,并把该数字添加到realValue变量的末尾。
你该想到,这是不能实现的。因为每次输入时当前位的数字是变化的,即temp是变化的,而变量realValue是由前十位可见数字+temp变量组成的,所以每次realValue最后的输出结果就只有11位数字,且realValue最后一位数字就是temp的值也是最后一次输入的最后一位的数字。如下:
const inputField = document.querySelector('#userName');
// 临时变量,记录当前输入位的数字
let temp = '';
// 完整的真实的身份证号
let realValue = '';
inputField.addEventListener('input', function (e) {
const inputValue = this.value.trim(); // 获取输入框中的值
// 判断输入长度是否超过十位数
if (inputValue.length > 10) {
// 取前十位可见
const visiblePart = inputValue.substring(0, 10);
// 记录当前输入的最后1位数字
temp = this.value[this.value.length - 1];
// 记录真实的身份证号:前十位 + 当前输入的最后一位
realValue = visiblePart + temp;
// 第十位后面的数字用*替换
const hiddenPart = inputValue.substring(0, inputValue.length - 10).replace(/./g, '*');
// 组合成脱敏后的值
const maskedValue = visiblePart + hiddenPart;
// 更新输入框中的显示值
this.value = maskedValue;
}
console.log('res', realValue);
})
所以,当我们在页面输入:aaaaaaaaaa200001019999时,最后的结果输出的却是: aaaaaaaaaa9
由于有了上次自动填充的思想,我们可以想到,使用一个对于用户不可见的input来记录真实的账号,在传递数据给后端时,就使用该不可见的input的值来进行传递。
于是,代码就变成了如下所示(记得隐藏第二个input输入框):
<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;
outline: none;
border: 1px solid #ccc;
}
input#realUserName {
display: none;
}
</style>
<div class="container">
<input type="text" id="userName" placeholder="请输入身份证号">
<input type="text" id="realUserName">
</div>
<script>
const inputField = document.querySelector('#userName');
const realUserName = document.querySelector('#realUserName');
inputField.addEventListener('input', function (e) {
// 获取输入框中的值
const inputValue = this.value.trim();
// 拼接每一次输入的当前数字
realUserName.value += inputValue.substring(inputValue.length - 1);
// 判断输入长度是否超过十位数
if (inputValue.length > 10) {
// 取前十位可见
const visiblePart = inputValue.substring(0, 10);
// 第十位后面的数字用*替换
const hiddenPart = inputValue.substring(0, inputValue.length - 10).replace(/./g, '*');
// 组合成脱敏后的值
const maskedValue = visiblePart + hiddenPart;
// 更新输入框中的显示值
this.value = maskedValue;
}
console.log('res', this.value, realUserName.value);
})
</script>
看看效果,
输入:aaaaaaaaaa200001019999,
输出:aaaaaaaaaa200001019999。
至此,基本的脱敏效果就完成了。
问题又又来了: 模拟用户输入,如果用户在输入第5位数时,把本该是a的输成了b,于是他使用删除键删除了b进行更正,继续输入正确的账号,那他能正确登录吗?答案是不能。因为我们在记录账号时使用的是简单的拼接,没有做其他的处理,所以就此埋下了bug。
如图,我们输入账号aaaaaaaaaa200001019999,但在此过程中,输入第5位数时由于输入错误,输成了b,并使用删除进行更正,最后输入了正确的账号。但在代码中的输出结果还是含有b的,这就会导致用户登录失败。
输出结果:aaaabaaaaaaa200001019999
4.第三回合:移花接木
这个问题有很多解决方法,这里提供一个思路,输入错误时,回退更正之后会导致两个input的值的长度不同,可以在监听事件中判断长度是否相同,如果不同,则是用户出现了回退行为,可以将被隐藏的输入框使用substring截取到与用户的输入框的值长度一致的位置。
// 防止用户回退输入时出现错误
if (inputValue.length != realUserName.value.length) {
realUserName.value = realUserName.value.substring(0, inputValue.length)
}
注意: substring截取结果不包括结束字符(顾头不顾尾)。
效果展示:
输入:aaaaaaaaaa200001019999
输出:aaaaaaaaaa200001019999
问题又又又来了: 如果用户输入账号时,使用鼠标或者键盘进行复制粘贴的输入呢?能登录成功吗?猜对了,不能!
5.第四回合:万佛归宗
当用户输入账号时,如果直接进行复制粘贴,input监听事件只能监听到最后一位数字,这会导致最终的结果只有最后一位数字,从而导致登录失败。这里可以直接使用赋值的方法,将用户的输入框的值直接赋值给被隐藏的输入框。那怎么判断出现了复制粘贴的情况呢?这不是和移花接木里面的情况一样嘛,长度不一样啊,所以知道为什么叫万佛朝宗了吧,直接开大招就是不一样,可以解决99%的问题。
输入:aaaaaaaaaa200001019999
输出:9
施展技能,万佛朝宗,返璞归真:
// 防止用户删除上一个输入值时出现错误
// 并且
// 防止用户通过粘贴输入值时只监听到最后一位数而出现的错误
if (inputValue.length != realUserName.value.length) {
realUserName.value = inputValue;
}
效果展示:
输入:aaaaaaaaaa200001019999
输出:aaaaaaaaaa200001019999
至此,就完成了对input输入框的脱敏功能。实现脱敏的方法很多,本文仅提供一些思路,如有其他更好的方法,欢迎交流!
另外,若对禁止浏览器的自动填充感兴趣的朋友,欢迎查看我的其他文章,链接地址在下方。里面阐述了对于不同浏览器(谷歌、火狐、Edge)该怎样禁止自动填充的说明,欢迎访问。
文章地址: https://blog.csdn.net/qq_51667621/article/details/139977451