jsp-servlet圖像驗證碼
實現圖像驗證碼類ImageValidateCode:
package com.myhome; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /** * 防止暴力破解,使用的圖像驗證碼 * */ public class ImageValidateCode extends HttpServlet { /** * 實現java.io.Serializable這個接口是為序列化, * serialVersionUID 用來表明實現序列化類的不同版本間的兼容性。 * 如果你修改了此類, 要修改此值。否則以前用老版本的類序列化的類恢複時會出錯。 * 為了在反序列化時,確保類版本的兼容性。序列化時為了保持版本的兼容性, * 即在版本升級時反序列化仍保持對象的唯一性。 */ private static final long serialVersionUID = 5403703649596352260L; //產生隨機數 private Random random =new Random(); //定義圖形驗證碼中繪製字符的字體,字體名稱,字體樣式,字體大小l;如:"Arial Black"或"Fixedsys", Font.CENTER_BASELINE, 18 private final Font mFont=new Font("Arial Black", Font.PLAIN, 24); //定義驗證碼的大小,即高度和寬度 private final int IMG_WIDTH=90; private final int IMG_HEIGHT=25; //幹擾線的數量 private final int LineSize=50; //產生的隨機字符數量 private int stringNum = 4; /** * 獲取隨機顏色的方法 * */ private Color getRandColor(int fc,int bc) { if(fc>255) { fc=255; } if(bc>255) { bc=255; } //產生隨機的RGB三原色 int r=fc+random.nextInt(bc-fc-16); int g=fc+random.nextInt(bc-fc-14); int b=fc+random.nextInt(bc-fc-18); return new Color(r, g, b); } /** * 獲取大、小寫字母和數字隨機字符串方法 * */ private String getRandString() { //Math.random()---random()方法,是返回一個[0,1)的浮點數。 //一般我們是這樣運用的,比如我要取一個1~9的隨機數int a=(int)(Math.random()*10)注意是是乘上10再轉。 //Math.round()方法,round 就是四舍五入, //math.round(-8.9) -9;math.round(-8.1) -8;math.round(8.9) 9;math.round(8.1) 8 //生成0、1、2的隨機數字 int randi=(int) Math.round(Math.random()*2); //用來存儲數據的ASC碼 long itmp=0; //用於存儲字符 char ctmp='\u0000'; //以“\u”開頭的是一個Unicode碼的字符,每一個'\u0000'都代表了一個空格。 //Unicode可同時包含65536個字符,ASCII/ANSI隻包含255個字符,實際上是Unicode的一個子集。 //Unicode字符通常用十六進製編碼方案表示,範圍在'\u0000'到'\uFFFF'之間。 //\u0000到\u00FF表示ASCII/ANSI字符。 //“\u”表示這是一個Unicode值.\u0000代表的應該是NULL,輸出控製台是一個空格... switch(randi) { //生成大寫字母 case 1: itmp=Math.round(Math.random()*25+65);//long類型 ctmp=(char) itmp;//char類型 return String.valueOf(ctmp);//String類型 //生成小寫字母 case 2: itmp=Math.round(Math.random()*25+97); ctmp=(char) itmp; return String.valueOf(ctmp); //生成數字 default : itmp=Math.round(Math.random()*9); return itmp+"";//將整型數字連接成字符串 } } /** * 繪製隨機字符串 * */ private String drawString(Graphics g,String randomString,int i) { g.setFont(mFont);//設置字符串字體 g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));//設置字符串顏色 String rands=getRandString(); randomString+=rands; g.translate(random.nextInt(3), random.nextInt(2));//設置畫在圖片上的文字的x,y坐標,隨即偏移值 g.drawString(rands, 18*i+5, 18);//字符間距設置為15px ,使用此圖形上下文的當前字體和顏色繪製由指定 string 給定的文本。最左側字符的基線位於此圖形上下文坐標係統的 (x, y) 位置處。即:str - 要繪製的 string。x - x 坐標。y - y 坐標。//從圖像左麵10個像素個像素(後15*i+10),距上麵16個像素的位置開始從左到右的方向輸出rands的值。 return randomString; } /** * 繪製幹擾線 * */ private void drawLine1(Graphics g) { //參數:x1 - 第一個點的 x 坐標。y1 - 第一個點的 y 坐標。x2 - 第二個點的 x 坐標。y2 - 第二個點的 y 坐標。x1和x2是起點坐標,x2和y2是終點坐標 int x=random.nextInt(IMG_WIDTH); int y=random.nextInt(IMG_HEIGHT); int x1=random.nextInt(13); int y1=random.nextInt(15); g.drawLine(x, y, x+x1, y+y1); } private void drawLine2(Graphics g) { //參數:x1 - 第一個點的 x 坐標。y1 - 第一個點的 y 坐標。x2 - 第二個點的 x 坐標。y2 - 第二個點的 y 坐標。x1和x2是起點坐標,x2和y2是終點坐標 int x=random.nextInt(IMG_WIDTH); int y=random.nextInt(IMG_HEIGHT); int x1=random.nextInt(13); int y1=random.nextInt(15); g.drawLine(x, y, x-x1, y-y1); } /** * 圖像驗證碼的生成 * */ @Override protected void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { System.out.println("驗證碼開始生成了"); //設置禁止緩存 response.setHeader("Pragma","No-cache"); response.setHeader("Cache-Control","no-cache"); response.setDateHeader("Expires", 0); response.setContentType("image/jpeg");//設置輸出流內容格式為圖片格式 /*禁用IE緩存 * HTTP消息報頭包括普通報頭、請求報頭、響應報頭、實體報頭。 * 普通報頭中的Cache-Control用於指定緩存指令,緩存指令是單向的(響應中出現的緩存指令在請求中未必會出現),且是獨立的(一個消息的緩存指令不會影響另一個消息處理的緩存機製),HTTP1.0使用的類似的報頭域為Pragma。 * 請求時的緩存指令包括:no-cache(用於指示請示或響應消息不能緩存)、no-store、max-age、max-stale、min-fresh、only-if-cached; * 響應時的緩存指令包括:public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age、s-maxage。 * 例:為了指示IE瀏覽器(客戶端)不要緩存頁麵,服務器端的jsp程序可以編寫如下:response.setHeader(“Cache-Control”, “no-cache”);//response.setHeader(“Pragma”, “no-cache”); * 作用相當於上行代碼,通常兩者合用Expires實體報頭域給出響應過期的日期和時間。為了讓代理服務器或瀏覽器在一段時間以後更新緩存中(再次訪問曾訪問過的頁麵時,直接從緩存中加載,縮短響應時間和降低服務器負載)的頁麵,我們可以使用Expires實體報頭域指定頁麵過期時間。 * 例:Expires:Thu,15 Sep 2006 16:23:12 GMTHTTP1.1的客戶端和緩存必須將其他非法的日期格式(包括0)看作已經過期。 * 如:為了讓瀏覽器不要緩存頁麵,也可以利用Expires實體報關域,設置為0,jsp程序如下:response.setDateHeader(“Expires”, “0”); * */ //在內存中創建一副圖像,寬90像素,高25像素,rgb模式的色彩 BufferedImage image=new BufferedImage(IMG_WIDTH, IMG_HEIGHT, BufferedImage.TYPE_INT_RGB); //在內存中創建一個畫筆 Graphics g=image.getGraphics(); //設置畫筆顏色 g.setColor(getRandColor(200, 250)); //填充背景色,使用當前的畫筆顏色修改圖片背景色 g.fillRect(1, 1, IMG_WIDTH-1, IMG_HEIGHT-1);//4個參數的意思分別為,起始X坐標,起始Y坐標,寬度,高度。 //為圖形驗證碼繪製邊框 g.setColor(new Color(155,155,155)); g.drawRect(0, 0, IMG_WIDTH,IMG_HEIGHT); //生成隨機幹擾線 g.setColor(getRandColor(110, 133)); for(int i=0;i<=LineSize;i++){ drawLine1(g); drawLine2(g); } //用於保存係統生成的隨機字符串 String randomString = ""; //繪製隨機字符串 for(int j=0;j<stringNum;j++){ randomString=drawString(g, randomString, j); } //獲取HttpSesssion對象 HttpSession session=request.getSession(true); //getSession(true):true: 如果session存在,則返回該session,否則創建一個新的session;false: 如果session存在,則返回該session,否則返回null. //將隨機字符串放入到HttpSession對象中,驗證碼中的隨機數不區分大小寫 session.setAttribute("rand", randomString.toLowerCase()); String rands=(String) session.getAttribute("rand"); System.out.println("驗證碼生成成功"+rands); System.out.println("驗證碼生成成功"+randomString.toLowerCase().toString()); //釋放畫筆對象 g.dispose(); //向輸出流中輸出圖像 ImageIO.write(image, "JPEG", response.getOutputStream()); } }
jsp界麵實現index.jsp和validat.jsp:
validat.jsp:
<body> <img src="checkServlet" /> <a href="validat.jsp" >看不清楚,換張圖片</a> </body>
index.jsp:
<head> <script type="text/javascript"> //看不清圖片,重新加載一張圖像驗證碼 function reloadVercode(){ document.getElementById("authImg").src="auth.jpg?now="+new Date(); } </script> </head> <body> <img src="auth.jpg" /><a href="javascript:void(null)" >看不清,換一張</a> </body>
web.xml配置:
<!-- 定義圖像驗證碼的servlet index.jsp配置--> <servlet> <servlet-name>img</servlet-name> <servlet-class>com.myhome.ImageValidateCode</servlet-class> </servlet> <servlet-mapping> <servlet-name>img</servlet-name> <url-pattern>/auth.jpg</url-pattern> </servlet-mapping> <!-- 定義圖像驗證碼的servlet validat.jsp配置--> <servlet> <servlet-name>CheckServlet</servlet-name> <servlet-class>com.myhome.ImageValidateCode</servlet-class> </servlet> <servlet-mapping> <servlet-name>CheckServlet</servlet-name> <url-pattern>/checkServlet</url-pattern> </servlet-mapping>
效果圖:
其他:
package com.myhome; public class Test { /** * 產生隨機字符串 * */ private String getRandomChar() { int rand = (int)Math.round(Math.random() * 2); System.out.println("隨機數:"+rand); long itmp = 0; char ctmp = '\u0000'; System.out.println("字符:"+ctmp); switch (rand) { case 1: itmp = Math.round(Math.random() * 25 + 65); String s1=getType(itmp); System.out.println(s1+itmp); ctmp = (char)itmp; String s2=getType(ctmp); System.out.println(s2+itmp); System.out.println(getType(String.valueOf(ctmp))+String.valueOf(ctmp)); return String.valueOf(ctmp); case 2: itmp = Math.round(Math.random() * 25 + 97); System.out.println(itmp); ctmp = (char)itmp; System.out.println(ctmp); System.out.println(String.valueOf(ctmp)); return String.valueOf(ctmp); default : itmp = Math.round(Math.random() * 9); String.valueOf(itmp); return itmp + ""; } } /** * 判斷對象的類型 * */ private <T> String getType(T t) { if(t instanceof String) { return "String"; }else if(t instanceof Integer) { return "int"; }else if(t instanceof Character) { return "char"; }else if(t instanceof Long) { return "long"; }else { return "don't know Type of" +t; } } public static void main(String[] args) { Test t=new Test(); t.getRandomChar(); } }
最後更新:2017-04-04 07:03:38