純前端JS實現的文字驗證碼
作者:邵發
本文是Java學習指南系列教程的官方配套文檔。內容介紹一種基於JavaScript繪製的純前端實現的驗證碼技術。本文附帶項目源碼及相關JAR包。
1. 驗證碼的作用
簡單地說,驗證碼是用於“防刷”的,防止用戶或機器人的高頻率的網頁刷新。舉一個例子,假設網站提供一個訂單查詢功能,示意圖如下。
( 項目演示http://127.0.0.1:8080/demo/test )
所謂的惡意刷新,就是瘋狂地點擊這個“查詢”按鈕。由於後臺的查詢操作往往要查詢數據庫,這個操作佔用CPU較高。如果對用戶的惡意刷新不加阻攔,則網站會由於負載太高而崩潰。
所以對高耗資源的服務接口,一般要使用驗證碼加以保護,使其無法輕易調用。加上驗證碼環節之後,用戶必須在人工輸入了正確的驗證碼之後,才能夠進入後面的查詢流程。輸入驗證碼需要一定時間,從而阻止了用戶的高頻刷新攻擊。
2. 純前端JS驗證碼的實現
驗證碼在工作原理上分爲兩種:純前端驗證,前端+後臺聯合驗證。
本文先介紹純前端驗證的方式,這種方式僅靠前端JS來完成驗證,理論上並不安全,僅僅是防範一些不會編程的小白髮起的低水平攻擊。
(1) 準備基礎字符序列,如下:
vf.charBase = 'abcdefghjkmnqprstuvwxyABCDEFGHJKLMNPQRSTUVWXY3456789';
(2) 使用JS的Math.random(),生成每組4字符的隨機數字,即驗證碼。
vf.random = function(n){
var result = '';
for(var i=0;i<n; i++)
{
var max = this.charBase.length;
var idx = Math.floor( Math.random()* max );
result += this.charBase.charAt(idx);
}
return result;
}
(3) 將生成的隨機驗證碼保存在全局變量中,
vf.verifyCode = vf.random(4);
(4) 使用JS的Canvas繪製技術,將它繪製出來,
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = '#f37b63' ;
var text = vf.verifyCode + '';
ctx.fillText(text, w/2, h/2);
現在網頁上的呈現爲:
注意這個Canvas是一個圖片,它裏面的文字是繪製出來的。在實際項目中,你可以在這個圖片上再添加一些干擾,使之難以識別一點。
(5) 在用戶點“查詢”時,先檢查用戶輸入的驗證碼是否正確
window.doQuery = function(){
var verifyCode = $('.verifyCode').val().trim();
if(verifyCode.toLowerCase() != vf.verifyCode.toLowerCase())
{
alert('驗證碼有誤');
vf.reset(); // 更換驗證碼
return;
}
// 繼續後續流程...
var req = {};
req.orderNumber = $('.orderNumber').val().trim();
Af.rest ('[[@{/query.do}]]' ,req, function(data){
alert('成功提交');
})
}
在整個流程中,用戶想要用查詢功能,就必須正確的填寫驗證碼。輸入驗證碼是需要幾秒時間的,從而阻止了用戶的‘瘋狂’點擊操作。
3. 純前端JS驗證的安全缺陷
以上驗證機制,理論上是不安全的。它只能阻止低水平的攻擊,無法防範真正的程序員的功擊。可以說,它是防君子不防‘小人’的。
對於程序員來說,可以直接編寫一個程序來發起HTTP交互。形如,
JSONObject jreq = new JSONObject();
jreq.put("orderNumber", "112233445566");
HttpUtil httpUtil = new HttpUtil();
String reply = httpUtil.post ("http://www.your.com/query.do", jreq.toString());
通過編程直接調用後臺的query.do接口,便可以發起攻擊,並不需要經過驗證碼的流程。所以上述的前端驗證形同虛設。在下一篇191122_02文章中,將介紹基於前後臺聯合驗證的安全的校驗機制。
本篇演示所用的項目源碼和JAR包在此處可以獲取。