为了安全考虑,很多有登录行为的网站,会对密码输入框进行保护。
本文介绍一种使用安全键盘的输入保护方式,可用于防键盘记录、防止自动点击。
如下图,该输入框带有一个虚拟键盘。
之所以称其为“安全键盘”,是因为两点:
其一、通过点击虚拟键盘上的按键进行输入,而不需要按下真实键盘上的键位,这样就可以防止很多系统中的后台软件记录按键、窃取密码;
其二、虚拟键盘上的键位,是打乱的,并且是实时随机的,每次页面刷新、每次输入都是不同的键位。如此,可以防止自动化工具或脚本发起的自动点击输入。
首先,对指定的输入框,不接受常规按键,而是使用通过虚拟键盘输入。其次,虚拟键盘上的键位,每次都要随机生成。
UI部分,在页面使用div、table模拟一个键盘,如下图:
核心功能是随机键位的产生,在本例中,使用了两种方法随机生成键位,如数字部分,使用sort方法:
字母部分,使用random方法:
对于输入内容,是直接给input输入框赋值:
为防止功能逻辑泄露,可对JAVAScript代码进行保护,比如使用JShaman(JS萨满)混淆加密上面的safe_keyword函数代码。
加密后,代码成为:
这是加密了一个函数的代码。当然也可以对整体JS代码全部加密,保护效果会更好。
以下给出完整源码,包含UI、css风格、JS源码,保存为html即可测试使用。
<html>
<head>
<style>
th,td {
border: 1px solid #ccc;
padding: 2px 0;
text-align: center;
cursor: pointer
}
div {
border: 1px solid #ccc;
float: left;
padding: 1px;
display: none;
}
</style>
</head>
<body>
<h3>安全键盘输入</h3>
<input id="input" readonly="readonly" style="width:475px; height: 80px;" onclick="hide_or_show();"/>
<br>
<div id="keyboard">
<table cellspacing="1" width="480" onclick="safe_keyword()">
<tr>
<td>~</td>
<td>!</td>
<td>@</td>
<td>#</td>
<td>$</td>
<td>%</td>
<td>^</td>
<td>&</td>
<td>*</td>
<td>(</td>
<td>)</td>
<td>_</td>
<td>+</td>
<td>|</td>
<td rowspan="2" width="120">退格</td>
</tr>
<tr>
<td>`</td>
<td class="num">1</td>
<td class="num">2</td>
<td class="num">3</td>
<td class="num">4</td>
<td class="num">5</td>
<td class="num">6</td>
<td class="num">7</td>
<td class="num">8</td>
<td class="num">9</td>
<td class="num">0</td>
<td>-</td>
<td>=</td>
<td></td>
</tr>
<tr>
<td id="safe">q</td>
<td id="safe">w</td>
<td id="safe">e</td>
<td id="safe">r</td>
<td id="safe">t</td>
<td id="safe">y</td>
<td id="safe">u</td>
<td id="safe">i</td>
<td id="safe">o</td>
<td id="safe">p</td>
<td>{</td>
<td>}</td>
<td>[</td>
<td>]</td>
<td colspan="2">切换大/小写</td>
</tr>
<tr>
<td id="safe">a</td>
<td id="safe">s</td>
<td id="safe">d</td>
<td id="safe">f</td>
<td id="safe">g</td>
<td id="safe">h</td>
<td id="safe">j</td>
<td id="safe">k</td>
<td id="safe">l</td>
<td>:</td>
<td>"</td>
<td>;</td>
<td>'</td>
<td colspan="3" rowspan="3">ENTER</td>
</tr>
<tr>
<td id="safe">z</td>
<td id="safe">x</td>
<td id="safe">c</td>
<td id="safe">v</td>
<td id="safe">b</td>
<td id="safe">n</td>
<td id="safe">m</td>
<td>
</td>
<td>></td>
<td>?</td>
<td>,</td>
<td>.</td>
<td>/</td>
</tr>
</table>
</div>
<script>
var htmlCode = {
"&": "&",
'"': """,
"<": "<",
">": ">",
}
//安全输入
function safe_keyword() {
//输入框
var input = document.getElementById("input");
var e = window.event || test.caller.arguments[0];
var el = e.target || e.srcElement;
if(el.tagName.toLowerCase() == "td" && el.rowSpan <= 1 && el.colSpan <= 1) {
var str = el.innerHTML;
str = htmlCode[str] || str;
input.value += str;
}
if(el.innerHTML == "退格") {
input.value = input.value.slice(0, -1);
}
if(el.innerHTML == "切换大/小写") {
var els = document.getElementsByTagName("td");
for(var i = 0, l = els.length; i < l; i++) {
var str = els[i].innerHTML;
if(/^[a-z]$/.test(str)) els[i].innerHTML = str.toUpperCase();
if(/^[A-Z]$/.test(str)) els[i].innerHTML = str.toLowerCase();
}
}
//按下回车时隐藏安全键盘
if(el.innerHTML == "ENTER") {
hide_or_show();
}
}
//显示或隐藏键盘
function hide_or_show() {
var el = document.getElementById("keyboard");
if(el.offsetWidth > 0) el.style.display = "none";
else {
el.style.display = "block";
random_numbers();
random_letters();
}
}
//随机字母键位
function random_letters() {
//字符集
var all_keywords = [];
for(k=65; k<91; k++){
all_keywords.push(String.fromCharCode(k).toLowerCase());
}
//td元素,即各键位
var els = document.getElementsByTagName("td");
//遍历td元素
for(i=0; i<els.length; i++) {
//键位上显示的内容,即各字母
var str = els[i].innerHTML;
//随机字母
var rnd_key = parseInt( all_keywords.length * Math.random() );
if(els[i].id == "safe"){
els[i].innerHTML = all_keywords[rnd_key];
//使用后删除
delete all_keywords[rnd_key];
all_keywords.splice(rnd_key,1);
}
}
}
//随机数字键位
function random_numbers() {
//随机排序数字
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].sort(function() {
return Math.random() > 0.5 ? 1 : -1;
});
//取得所有键位
var els = document.getElementsByTagName("td");
for(var i = 0, j = 0, l = els.length; i < l; i++) {
//键位上的字符
var str = els[i].innerHTML;
//用正则表达式判断是不是数字键位,并赋新的随机值
if(/^d$/.test(str)) els[i].innerHTML = arr[j++];
}
}
</script>
</body>
</html>