做一個登入頁面,添加圖片驗證碼,需要頁面,Action跳轉,struts.xml傳輸映像資料,隨機產生字元的類,還有使用隨機字元產生圖片的類。
剩下就是頁面登入時,產生圖片,資料校正進行匹配了。
ValidateCode.java
import java.util.Arrays;/** * 工具類,產生隨機驗證碼字串 * @version 1.0 2012/08/21 * @author * */public class ValidateCode { /** * 驗證碼難度層級,Simple只包含數字,Medium包含數字和小寫英文,Hard包含數字和大小寫英文 */ public enum SecurityCodeLevel {Simple,Medium,Hard}; /** * 產生預設驗證碼,4位中等難度 * @return String 驗證碼 */ public static String getSecurityCode(){ return getSecurityCode(4,SecurityCodeLevel.Medium,false); } /** * 產生長度和難度任意的驗證碼 * @param length 長度 * @param level 難度層級 * @param isCanRepeat 是否能夠出現重複的字元,如果為true,則可能出現 5578這樣包含兩個5,如果為false,則不可能出現這種情況 * @return String 驗證碼 */ public static String getSecurityCode(int length,SecurityCodeLevel level,boolean isCanRepeat){ //隨機抽取len個字元 int len=length; //字元集合(除去易混淆的數字0、數字1、字母l、字母o、字母O) char[] codes={'1','2','3','4','5','6','7','8','9', 'a','b','c','d','e','f','g','h','i', 'j','k','m','n','p','q','r','s','t', 'u','v','w','x','y','z','A','B','C', 'D','E','F','G','H','I','J','K','L', 'M','N','P','Q','R','S','T','U','V', 'W','X','Y','Z'}; //根據不同的難度截取字元數組 if(level==SecurityCodeLevel.Simple){ codes=Arrays.copyOfRange(codes, 0,9); }else if(level==SecurityCodeLevel.Medium){ codes=Arrays.copyOfRange(codes, 0,33); } //字元集合長度 int n=codes.length; //拋出運行時異常 if(len>n&&isCanRepeat==false){ throw new RuntimeException( String.format("調用SecurityCode.getSecurityCode(%1$s,%2$s,%3$s)出現異常," + "當isCanRepeat為%3$s時,傳入參數%1$s不能大於%4$s", len,level,isCanRepeat,n)); } //存放抽取出來的字元 char[] result=new char[len]; //判斷能否出現重複的字元 if(isCanRepeat){ for(int i=0;i<result.length;i++){ //索引 0 and n-1 int r=(int)(Math.random()*n); //將result中的第i個元素設定為codes[r]存放的數值 result[i]=codes[r]; } }else{ for(int i=0;i<result.length;i++){ //索引 0 and n-1 int r=(int)(Math.random()*n); //將result中的第i個元素設定為codes[r]存放的數值 result[i]=codes[r]; //必須確保不會再次抽取到那個字元,因為所有抽取的字元必須不相同。 //因此,這裡用數組中的最後一個字元改寫codes[r],並將n減1 codes[r]=codes[n-1]; n--; } } return String.valueOf(result); }}
ValidateImg.java
import java.awt.Color;import java.awt.Font;import java.awt.Graphics;import java.awt.image.BufferedImage;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.util.Random;import com.sun.image.codec.jpeg.ImageFormatException;import com.sun.image.codec.jpeg.JPEGCodec;import com.sun.image.codec.jpeg.JPEGImageEncoder;/** * 工具類,產生驗證碼圖片 * @version 1.0 2012/08/21 * @author * */public class ValidateImage { /** * 產生驗證碼圖片 * @param securityCode 驗證碼字元 * @return BufferedImage 圖片 */ public static BufferedImage createImage(String securityCode){ //驗證碼長度 int codeLength=securityCode.length(); //字型大小 int fSize = 15; int fWidth = fSize + 1; //圖片寬度 int width = codeLength * fWidth + 6 ; //圖片高度 int height = fSize * 2 + 1; //圖片 BufferedImage image=new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics g=image.createGraphics(); //設定背景色 g.setColor(Color.WHITE); //填充背景 g.fillRect(0, 0, width, height); //設定邊框顏色 g.setColor(Color.LIGHT_GRAY); //邊框字型樣式 g.setFont(new Font("Arial", Font.BOLD, height - 2)); //繪製邊框 g.drawRect(0, 0, width - 1, height -1); //繪製噪點 Random rand = new Random(); //設定噪點顏色 g.setColor(Color.LIGHT_GRAY); for(int i = 0;i < codeLength * 6;i++){ int x = rand.nextInt(width); int y = rand.nextInt(height); //繪製1*1大小的矩形 g.drawRect(x, y, 1, 1); } //繪製驗證碼 int codeY = height - 10; //設定字型顏色和樣式 g.setColor(new Color(19,148,246)); g.setFont(new Font("Georgia", Font.BOLD, fSize)); for(int i = 0; i < codeLength;i++){ g.drawString(String.valueOf(securityCode.charAt(i)), i * 16 + 5, codeY); } //關閉資源 g.dispose(); return image; } /** * 返回驗證碼圖片的流格式 * @param securityCode 驗證碼 * @return ByteArrayInputStream 圖片流 */ public static ByteArrayInputStream getImageAsInputStream(String securityCode){ BufferedImage image = createImage(securityCode); return convertImageToStream(image); } /** * 將BufferedImage轉換成ByteArrayInputStream * @param image 圖片 * @return ByteArrayInputStream 流 */ private static ByteArrayInputStream convertImageToStream(BufferedImage image){ ByteArrayInputStream inputStream = null; ByteArrayOutputStream bos = new ByteArrayOutputStream(); JPEGImageEncoder jpeg = JPEGCodec.createJPEGEncoder(bos); try { jpeg.encode(image); byte[] bts = bos.toByteArray(); inputStream = new ByteArrayInputStream(bts); } catch (ImageFormatException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return inputStream; }}
ValidateAction.action
import java.io.ByteArrayInputStream;import java.util.Map;import org.apache.struts2.interceptor.SessionAware;import com.opensymphony.xwork2.ActionSupport;public class ValidAction extends ActionSupport implements SessionAware{//Struts2中Map類型的sessionprivate Map<String, Object> session;//圖片流private ByteArrayInputStream imageStream;public String valid(){<span style="white-space:pre"></span>//如果開啟Hard模式,可以不區分大小寫<span style="white-space:pre"></span>// String securityCode = ValidateCode.getSecurityCode(4,SecurityCodeLevel.Hard, false).toLowerCase(); //擷取預設難度和長度的驗證碼 String securityCode = ValidateCode.getSecurityCode(); imageStream = ValidateImg.getImageAsInputStream(securityCode); //放入session中 session.put("SESSION_SECURITY_CODE", securityCode); return SUCCESS;}public void setSession(Map<String, Object> session) {this.session = session;}public ByteArrayInputStream getImageStream() {return imageStream;}public void setImageStream(ByteArrayInputStream imageStream) {this.imageStream = imageStream;}public Map<String, Object> getSession() {return session;}}struts.xml
<action name="valid" class="com.web.action.ValidAction" method="valid"><result name="success" type="stream"> <param name="contentType">image/jpeg</param> <param name="inputName">imageStream</param> <param name="bufferSize">2048</param> </result></action>
login.jsp
<pre name="code" class="html"><script language="JavaScript" type="text/JavaScript">
function changeImage(){<span style="white-space:pre"></span>var rom = parseInt(100000000000*Math.random());<span style="white-space:pre"></span>document.getElementById("imageValid").src="<%=basePath%>valid.action?timeStamp="+rom;}window.onload=function(){<span style="white-space:pre"></span>var rom = parseInt(100000000000*Math.random());<span style="white-space:pre"></span>document.getElementById("userName").focus();<span style="white-space:pre"></span>document.getElementById("imageValid").src="<%=basePath%>valid.action?timeStamp="+rom;<span style="white-space:pre"></span>$("#fbl").val(document.documentElement.clientHeight);}</script>
<input name="valid" id="validNum" maxlength="4" class="loginImgNum"/><span> <img src="" width=55 height="37px" style="vertical-align:bottom;border:0px;" id="imageValid" onclick="changeImage()"/></span>