生成验证码的工具类:VerifyCodeUtils(有几种实现方式,放入流,保存文件等)
public class VerifyCodeUtils { //使用到Algerian字体,系统里没有的话需要安装字体,字体只显示大写,去掉了1,0,i,o几个容易混淆的字符 public static final String VERIFY_CODES = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ"; private static Random random = new Random(); /** * 使用系统默认字符源生成验证码 * @param verifySize 验证码长度 * @return */ public static String generateVerifyCode(int verifySize){ return generateVerifyCode(verifySize, VERIFY_CODES); } /** * 使用指定源生成验证码 * @param verifySize 验证码长度 * @param sources 验证码字符源 * @return */ public static String generateVerifyCode(int verifySize, String sources){ if(sources == null || sources.length() == 0){ sources = VERIFY_CODES; } int codesLen = sources.length(); Random rand = new Random(System.currentTimeMillis()); StringBuilder verifyCode = new StringBuilder(verifySize); for(int i = 0; i < verifySize; i++){ verifyCode.append(sources.charAt(rand.nextInt(codesLen-1))); } return verifyCode.toString(); } /** * 生成随机验证码文件,并返回验证码值 * @param w * @param h * @param outputFile * @param verifySize * @return * @throws IOException */ public static String outputVerifyImage(int w, int h, File outputFile, int verifySize) throws IOException{ String verifyCode = generateVerifyCode(verifySize); outputImage(w, h, outputFile, verifyCode); return verifyCode; } /** * 输出随机验证码图片流,并返回验证码值 * @param w * @param h * @param os * @param verifySize * @return * @throws IOException */ public static String outputVerifyImage(int w, int h, OutputStream os, int verifySize) throws IOException{ String verifyCode = generateVerifyCode(verifySize); outputImage(w, h, os, verifyCode); return verifyCode; } /** * 生成指定验证码图像文件 * @param w * @param h * @param outputFile * @param code * @throws IOException */ public static void outputImage(int w, int h, File outputFile, String code) throws IOException{ if(outputFile == null){ return; } File dir = outputFile.getParentFile(); if(!dir.exists()){ dir.mkdirs(); } try{ outputFile.createNewFile(); FileOutputStream fos = new FileOutputStream(outputFile); outputImage(w, h, fos, code); fos.close(); } catch(IOException e){ throw e; } } /** * 输出指定验证码图片流 * @param w * @param h * @param os * @param code * @throws IOException */ public static void outputImage(int w, int h, OutputStream os,String code)throwsIOException{ int verifySize = code.length(); BufferedImage image =newBufferedImage(w, h,BufferedImage.TYPE_INT_RGB); Random rand =newRandom(); Graphics2D g2 = image.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); Color[] colors =newColor[5]; Color[] colorSpaces =newColor[]{Color.WHITE,Color.CYAN, Color.GRAY,Color.LIGHT_GRAY,Color.MAGENTA,Color.ORANGE, Color.PINK,Color.YELLOW }; float[] fractions =newfloat[colors.length]; for(int i =0; i < colors.length; i++){ colors[i]= colorSpaces[rand.nextInt(colorSpaces.length)]; fractions[i]= rand.nextFloat(); } Arrays.sort(fractions); g2.setColor(Color.GRAY);// 设置边框色 g2.fillRect(0,0, w, h); Color c = getRandColor(200,250); g2.setColor(c);// 设置背景色 g2.fillRect(0,2, w, h-4); //绘制干扰线 Random random =newRandom(); g2.setColor(getRandColor(160,200));// 设置线条的颜色 for(int i =0; i <20; i++){ int x = random.nextInt(w -1); int y = random.nextInt(h -1); int xl = random.nextInt(6)+1; int yl = random.nextInt(12)+1; g2.drawLine(x, y, x + xl +40, y + yl +20); } // 添加噪点 float yawpRate =0.05f;// 噪声率 int area =(int)(yawpRate * w * h); for(int i =0; i < area; i++){ int x = random.nextInt(w); int y = random.nextInt(h); int rgb = getRandomIntColor(); image.setRGB(x, y, rgb); } shear(g2, w, h, c);// 使图片扭曲 g2.setColor(getRandColor(100,160)); int fontSize = h-4; Font font =newFont("Algerian",Font.ITALIC, fontSize); g2.setFont(font); char[] chars = code.toCharArray(); for(int i =0; i < verifySize; i++){ AffineTransform affine =newAffineTransform(); affine.setToRotation(Math.PI /4* rand.nextDouble()*(rand.nextBoolean()?1:-1),(w / verifySize)* i + fontSize/2, h/2); g2.setTransform(affine); g2.drawChars(chars, i,1,((w-10)/ verifySize)* i +5, h/2+ fontSize/2-10); } g2.dispose(); ImageIO.write(image,"jpg", os); } privatestaticColor getRandColor(int fc,int bc){ if(fc >255) fc =255; if(bc >255) bc =255; int r = fc + random.nextInt(bc - fc); int g = fc + random.nextInt(bc - fc); int b = fc + random.nextInt(bc - fc); returnnewColor(r, g, b); } privatestaticint getRandomIntColor(){ int[] rgb = getRandomRgb(); int color =0; for(int c : rgb){ color = color <<8; color = color | c; } return color; } privatestaticint[] getRandomRgb(){ int[] rgb =newint[3]; for(int i =0; i <3; i++){ rgb[i]= random.nextInt(255); } return rgb; } privatestaticvoid shear(Graphics g,int w1,int h1,Color color){ shearX(g, w1, h1, color); shearY(g, w1, h1, color); } privatestaticvoid shearX(Graphics g,int w1,int h1,Color color){ int period = random.nextInt(2); boolean borderGap =true; int frames =1; int phase = random.nextInt(2); for(int i =0; i < h1; i++){ double d =(double)(period >>1) *Math.sin((double) i /(double) period +(6.2831853071795862D*(double) phase) /(double) frames); g.copyArea(0, i, w1,1,(int) d,0); if(borderGap){ g.setColor(color); g.drawLine((int) d, i,0, i); g.drawLine((int) d + w1, i, w1, i); } } } privatestaticvoid shearY(Graphics g,int w1,int h1,Color color){ int period = random.nextInt(40)+10;// 50; boolean borderGap =true; int frames =20; int phase =7; for(int i =0; i < w1; i++){ double d =(double)(period >>1) *Math.sin((double) i /(double) period +(6.2831853071795862D*(double) phase) /(double) frames); g.copyArea(i,0,1, h1,0,(int) d); if(borderGap){ g.setColor(color); g.drawLine(i,(int) d, i,0); g.drawLine(i,(int) d + h1, i, h1); } } } publicstaticvoid main(String[] args)throwsIOException{ File dir =newFile("c:/verifies"); int w =200, h =80; // for(int i = 0; i < 50; i++){ String verifyCode = generateVerifyCode(4); File file =newFile(dir, verifyCode +".jpg"); outputImage(w, h, file, verifyCode); // } } }
2.servlet:CaptchaServlet
public class CaptchaServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setHeader("Pragma", "No-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); response.setContentType("image/jpeg"); //(先生成字符串保存,然后在把字符串绘制到图画) //生成随机字串 String verifyCode = VerifyCodeUtils.generateVerifyCode(4); //存入会话session HttpSession session = request.getSession(true); DoradoContext context = DoradoContext.getCurrent(); session.setAttribute("code", verifyCode.toLowerCase()); //生成图片 int w = 120, h = 30; VerifyCodeUtils.outputImage(w, h, response.getOutputStream(), verifyCode); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
4.web.xml
<servlet-mapping> <servlet-name>doradoServlet</servlet-name> <url-pattern>/dorado/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>CaptchaServlet</servlet-name> <url-pattern>/servlet/CaptchaServlet</url-pattern> </servlet-mapping>
5.调用
<div class="input-append"> <input id="captcha" type="text" name="j_captcha" /> <div class="add-on"> <img id="captchaImage" src="servlet/CaptchaServlet" /> </div> </div>