為了安全考慮,很多有登錄行為的網站,會對密碼輸入框進行保護。
本文介紹一種使用安全鍵盤的輸入保護方式,可用于防鍵盤記錄、防止自動點擊。
效果展示
如下圖,該輸入框帶有一個虛擬鍵盤。
之所以稱其為“安全鍵盤”,是因為兩點:
其一、通過點擊虛擬鍵盤上的按鍵進行輸入,而不需要按下真實鍵盤上的鍵位,這樣就可以防止很多系統中的后臺軟件記錄按鍵、竊取密碼;
其二、虛擬鍵盤上的鍵位,是打亂的,并且是實時隨機的,每次頁面刷新、每次輸入都是不同的鍵位。如此,可以防止自動化工具或腳本發起的自動點擊輸入。
功能原理
首先,對指定的輸入框,不接受常規按鍵,而是使用通過虛擬鍵盤輸入。其次,虛擬鍵盤上的鍵位,每次都要隨機生成。
源碼解析
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>