丁乙詩(shī) 任云宏 蘭全祥
摘要:驗(yàn)證碼能夠有效防止暴力破解、惡意灌水以及自動(dòng)注冊(cè)等,在WEB開發(fā)中具有至關(guān)重要的作用。首先對(duì)Servlet技術(shù)進(jìn)行了簡(jiǎn)介,其次按照MVC架構(gòu)模式對(duì)驗(yàn)證碼的實(shí)現(xiàn)進(jìn)行了分析,并闡述了驗(yàn)證碼的實(shí)現(xiàn)步驟。最后,重點(diǎn)講解了字符型驗(yàn)證碼、中文驗(yàn)證碼的設(shè)計(jì)原理及實(shí)現(xiàn),同時(shí)介紹了為驗(yàn)證碼添加干擾的方法。
關(guān)鍵詞:Servlet;驗(yàn)證碼;干擾;網(wǎng)站開發(fā)
中圖分類號(hào):TP311.1 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1009-3044(2018)20-0025-02
Design and Implementation of Verification Code Based on Servlet
DING Yi-shi, REN Yun-hong, LAN Quan-xiang
(Panzhihua University, Panzhihua 617000, China)
Abstract: Verification code can effectively prevent brute force, spam and automatic registration. It plays an important role in WEB development. First, the Servlet technology is introduced. Secondly, the implementation of the verification code is analyzed Based on the MVC architecture mode, and the development steps of the verification code are described. Finally, the design principles and implementation of character and Chinese verification code are explained. This paper introduces the method of adding interference to the verification code.
Key words: servlet; verification code; interference; website development
1 背景
驗(yàn)證碼又稱為全自動(dòng)區(qū)分計(jì)算機(jī)和人類的圖靈測(cè)試(CAPTCHA,Completely Automated Public Turing test to tell Computers and Humans Apart),是一種區(qū)分用戶是計(jì)算機(jī)還是人的公共全自動(dòng)程序。它能有效防止某些惡意用戶對(duì)某些特定用戶或網(wǎng)站使用暴力破解等方式進(jìn)行的不斷的非法攻擊,如自動(dòng)注冊(cè)、重復(fù)登錄、刷票、論壇灌水等[1]。
驗(yàn)證碼經(jīng)過(guò)長(zhǎng)期的發(fā)展,已經(jīng)演變出了圖片驗(yàn)證碼、知識(shí)型問(wèn)題驗(yàn)證碼、行為型驗(yàn)證碼、短信驗(yàn)證碼、信息校驗(yàn)驗(yàn)證碼,其中圖片驗(yàn)證碼是設(shè)計(jì)難度較低且應(yīng)用最廣泛的驗(yàn)證碼之一[2]。圖片驗(yàn)證碼一般是由數(shù)字、英文以及中文組成,其位數(shù)一般為四位,位數(shù)越多,識(shí)別難度越大。
2 Servlet技術(shù)簡(jiǎn)介
Servlet是用Java編寫的服務(wù)器端程序,主要功能在于交互式地訪問(wèn)和修改數(shù)據(jù),并生成動(dòng)態(tài)Web內(nèi)容。
2.1 Servlet API
Servle實(shí)現(xiàn)了javax.servlet.Servletr接口,在Servlet接口中定義了三個(gè)方法,分別為init方法、service方法和destroy方法。
init()方法主要用于servlet容器創(chuàng)建servlet實(shí)例時(shí)進(jìn)行Servlet初始化;service()方法用于處理客戶端向服務(wù)器發(fā)出的請(qǐng)求,并對(duì)服務(wù)器的響應(yīng)進(jìn)行設(shè)置;destroy()方法用于在服務(wù)器停止時(shí)銷毀Servlet。
2.2 Servelet的創(chuàng)建與配置
Servlet的創(chuàng)建實(shí)質(zhì)上是創(chuàng)建一個(gè)繼承了HttpServlet類的Java類,創(chuàng)建時(shí)應(yīng)遵循命名規(guī)范(類名首字母大寫)。
在Tomcat6.0之后,Servlet可以通過(guò)注解進(jìn)行配置,具體配置為:@WebServlet(urlPatterns = {" urlPatterns "}),其中urlPatterns屬性用于指定servlet的映射路徑。
3 驗(yàn)證碼設(shè)計(jì)
一般情況下,WEB開發(fā)都是按照MVC三層結(jié)構(gòu)進(jìn)行設(shè)計(jì)的,因此筆者從視圖層、控制層、模型層分別對(duì)驗(yàn)證碼的設(shè)計(jì)和實(shí)現(xiàn)進(jìn)行闡述。
3.1 視圖層
視圖層主要用于顯示驗(yàn)證碼和用戶輸入驗(yàn)證碼。在視圖層需編寫驗(yàn)證碼圖片代碼:
title="點(diǎn)擊刷新"
onclick="checkCode()" id="imge"/>
其中,ImgServlet為驗(yàn)證碼的請(qǐng)求地址(控制層Servlet映射URL),當(dāng)驗(yàn)證碼無(wú)法識(shí)別時(shí),用戶可以點(diǎn)擊驗(yàn)證碼進(jìn)行刷新,關(guān)鍵代碼如下:
function checkCode(){
imge.src = "ImgServlet?nocache="
+new Date().getTime();
}
3.2 控制層
控制層主要由Servlet技術(shù)來(lái)實(shí)現(xiàn),其主要用于接收視圖層發(fā)送的請(qǐng)求(生成驗(yàn)證碼),并調(diào)用模型層進(jìn)行數(shù)據(jù)處理,再將結(jié)果(驗(yàn)證碼圖片)響應(yīng)到視圖層。在控制層實(shí)現(xiàn)中需注意禁止圖片緩存并設(shè)置響應(yīng)類型為圖片。
禁止緩存是為了確保驗(yàn)證碼及時(shí)刷新,保證驗(yàn)證碼的有效性,關(guān)鍵代碼如下:
Response.setHeader("Pragma","No-cache");
Response.setHeader("Cache-Control","No-cache");
Response.setDateHeader("Expires","0");
由于請(qǐng)求的數(shù)據(jù)是圖片,因此需設(shè)置響應(yīng)內(nèi)容類型,關(guān)鍵代碼如下:
Response.setContentType("image/jpeg");
除上述步驟外,控制層還需調(diào)用模型層生成驗(yàn)證碼的方法,并將正確的驗(yàn)證碼字符保存到session中,然后將生成的驗(yàn)證碼圖片響應(yīng)到視圖層。
3.3 模型層
模型層是實(shí)現(xiàn)驗(yàn)證碼生成的java類。在這個(gè)類中主要通過(guò)隨機(jī)數(shù)生成器(Random)產(chǎn)生正確的驗(yàn)證碼字符,并使用GDI+(Graphics Device Interface plus,圖形設(shè)備接口)技術(shù)來(lái)實(shí)現(xiàn)驗(yàn)證碼的繪制[3]。
4 驗(yàn)證碼設(shè)計(jì)與實(shí)現(xiàn)
4.1 字符驗(yàn)證碼
字符驗(yàn)證碼一般包含英文和數(shù)字,這種驗(yàn)證碼實(shí)現(xiàn)簡(jiǎn)單、快速,但是識(shí)別難度低,容易被破解。字符驗(yàn)證碼的設(shè)計(jì)和實(shí)現(xiàn)步驟如下:
1)初始化驗(yàn)證碼字符串
String ctmp = "";
2)將待選字符存入數(shù)組
char [] char = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
3)從數(shù)組中隨機(jī)選取n個(gè)字符
Random random = new Random();
for(int i = 0; i int index=random.nextInt(char.length); ctmp += char[index];} 4)將驗(yàn)證碼繪制在圖片上 graphics.drawString(code, x, y); 其中,graphics為驗(yàn)證碼圖片的畫筆,code為正確驗(yàn)證碼字符,x和y是繪制驗(yàn)證碼的坐標(biāo)。生成的驗(yàn)證碼示例圖如圖1所示。 4.2 中文驗(yàn)證碼 由于字符型驗(yàn)證碼識(shí)別難度較低,為了提高驗(yàn)證碼的識(shí)別難度,在生成驗(yàn)證碼時(shí)可以選擇繪制中文字符。GB2312編碼規(guī)定漢字由四個(gè)區(qū)位碼組成,其中漢字編碼范圍為B0A1—F7FE,且從區(qū)位D7開始以后的漢字都是和很難見到的繁雜漢字(不適用于生成驗(yàn)證碼),因此驗(yàn)證碼所選范圍為B0A1—D7FE[4]。又因?yàn)閰^(qū)位碼表每區(qū)的第一個(gè)位置和最后一個(gè)位置為空,因此??A0和??FF不可?。ㄈ鏐1區(qū)的B1A0和B1FF不可?。V形尿?yàn)證碼生成流程圖如圖3所示。 1)初始化驗(yàn)證碼字符串 String ctmp=""; 2)初始化區(qū)位碼數(shù)組 String []rbase = {"0","1","2","3","4","5","6","7","8","9","a","b","c","d","d","e","f"}; 3)隨機(jī)生成n個(gè)漢字 Random random = new Random(); for(int i=0; i //生成第一位區(qū)碼 int r1 = random.nextInt(3)+11; String str_r1 = rbase[r1]; //根據(jù)第一位區(qū)碼生成第二位區(qū)碼 int r2; if(r1==13){ r2 = random.nextInt(7); }else{r2 = random.nextInt(16);} String str_r2 = rbase[r2]; //生成第一位位碼 int r3 = random.nextInt(6)+10; String str_r3 = rbase[r3]; //根據(jù)第一位位碼生成第二位位碼 int r4; if(r3==10){r4 = random.nextInt(15)+1; }else if(r3==15){r4 = random.nextInt(15); }else{r4 = random.nextInt(16);} String str_r4 = rbase[r4]; //將四位區(qū)位碼轉(zhuǎn)為字節(jié)數(shù)組 byte[] bytes = new byte[2]; String str_r12 = str_r1+str_r2; int tempLow = Integer.parseInt(str_r12,16); bytes[0] = (byte)tempLow; String str_r34 = str_r3+str_r4; int tempHigh = Integer.parseInt(str_r34,16); bytes[1] = (byte)tempHigh; //根據(jù)字節(jié)數(shù)組生成漢字 code = new String(bytes); ctmp+=code;
}
4)將驗(yàn)證碼繪制在圖片上
graphics.drawString(ctmp, x, y);
生成的驗(yàn)證碼示例圖片如圖2所示:
4.3 添加干擾
為了增加識(shí)別難度,可以在驗(yàn)證碼圖片上添加干擾,如隨機(jī)線、隨機(jī)顏色、隨機(jī)縮放拉伸、背景干擾、旋轉(zhuǎn)隨機(jī)角度等[5]。
1)添加隨機(jī)干擾線
int n = random.nextInt(15)+20;
//隨機(jī)生成20-35條干擾線;
for (int i = 0; i //隨機(jī)生成干擾線的起點(diǎn)和終點(diǎn) int xstart = (int)(Math.random() * width); int ystart = (int)(Math.random() * height); int xend = (int)(Math.random() * width); int yend = (int)(Math.random() * height); g.drawLine(xstart, ystart, xend, yend); } 2)縮放和隨機(jī)旋轉(zhuǎn) Graphics2D g2d = (Graphics2D) g; AffineTransform trans=new AffineTransform(); trans.rotate(random.nextInt(45) * Math.PI / 180, anchorx, anchory); float scaleSize = random.nextFloat() +0.8f; if (scaleSize > 1f) scaleSize = 1f; trans.scale(scaleSize, scaleSize); g2d.setTransform(trans); 添加隨機(jī)干擾線之后的驗(yàn)證碼實(shí)例如圖3所示: 5 結(jié)束語(yǔ) 驗(yàn)證碼能夠有效防止自動(dòng)注冊(cè)、暴力破解(重復(fù)登錄嘗試)、惡意灌水等行為。該文介紹了基于Servlet的驗(yàn)證碼生成技術(shù),講解了最廣泛使用的基于數(shù)字與英文字母的驗(yàn)證碼以及破解難度大和安全性高的中文驗(yàn)證碼。為了提高驗(yàn)證碼的識(shí)別難度,還介紹了添加干擾的方法。驗(yàn)證碼作為網(wǎng)絡(luò)服務(wù)的一種標(biāo)準(zhǔn)安全保障已被廣泛使用,其實(shí)現(xiàn)技術(shù)也是開發(fā)人員必須要掌握的技能之一。 參考文獻(xiàn): [1] 龔莎. 網(wǎng)頁(yè)驗(yàn)證碼技術(shù)綜述[J]. 信息與電腦: 理論版, 2014(2): 143-144. [2] 張立新. 多種類型驗(yàn)證碼的研究與分析[J]. 福建電腦, 2016, 32(10): 76, 125. [3] 李軍, 連俊光. 基于GDI+的Web端頁(yè)面驗(yàn)證碼繪制[J]. 電腦知識(shí)與技術(shù), 2018, 14(3): 72-73. [4] 李凱勝. 中文驗(yàn)證碼識(shí)別技術(shù)研究[D]. 西安: 西安電子科技大學(xué), 2014. [5] 藺佳哲, 王茜, 謝楠. 基于WEB開發(fā)技術(shù)的新型驗(yàn)證碼的設(shè)計(jì)研究[J]. 石家莊學(xué)院學(xué)報(bào),2016, 18(3): 38-41.