验证码的生成在网络上有很多相关的代码,在这里也自己写了个产生验证码的类,考虑到验证码在应用启动的时候就要生成,这时要将生成验证码代码放在一个servlet当中,当然验证码的作用是为了防止暴力破解,意思就是防止某个程序利用规律来破解用户名和密码简单的用户,如果不产生验证码那么很容易就被盗号,所以验证码就产生了,但是验证码如果发生缓存情况的话,也是很容易被破解的,所以验证码也不能在请求页面当中被缓存。方法如下:
// 设置Servlet不被缓存 response.setHeader("Pragma", "No-cache"); response.setHeader("Cache-Control", "no-cache");//浏览器和缓存服务器都不应该缓存页面信息 response.setDateHeader("Expires", 0);//指浏览器或缓存服务器在该时间点后必须从真正的服务器中获取新的页面信息验证码生成的实现无非就是随机生成图片或者字符串,干扰线等等,具体的代码如下:
/* 生成随机颜色 */ private static Color getRandomColor(int fc, int bc) { Random random = new Random(System.currentTimeMillis()); if (fc > 0xff) fc = 0xff; if (bc > 0xff) bc = 0xff; int r = fc + random.nextInt(bc - fc); int g = fc + random.nextInt(bc - fc); int b = fc + random.nextInt(bc - fc); return new Color(r, g, b); }/* 生成随机字符 */ private static String getRandomChar() { int rand = (int) Math.round(Math.random() * 2); // int itmp = 0; // char ctmp = '\u0000'; switch (rand) { case 1: return String.valueOf((char) Math.round(Math.random() * 25 + 65)); case 2: return String.valueOf((char) Math.round(Math.random() * 25 + 97)); default: return String.valueOf(Math.round(Math.random() * 9)); } }/* 生成随机验证码字符串。 */ private static String getRandomString() { StringBuffer code = new StringBuffer(); String temp = ""; for (int i = 0; i < LENGTH_OF_CODE; i++) { temp = getRandomChar(); while (true) { if("0".equals(temp) || "O".equals(temp) || "o".equals(temp) || "I".equals(temp) || "l".equals(temp)) { temp = getRandomChar(); } else { break; } } code.append(temp); } return code.toString(); }// 生成一张新的图片 BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); // 获取图形上下文 Graphics g = image.getGraphics(); Random random = new Random(System.currentTimeMillis()); // 准备在图片上绘制内容 g.setColor(getRandomColor(200, 250)); g.fillRect(1, 1, WIDTH - 1, HEIGHT - 1); g.setColor(new Color(155, 165, 175)); g.drawRect(0, 0, WIDTH - 1, HEIGHT - 1); // 设置字体 g.setFont(new Font("Lucida Grande", Font.BOLD, 20)); // 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到 for (int i = 0; i < 155; i++) { int x = random.nextInt(WIDTH - 1); int y = random.nextInt(HEIGHT - 1); int x1 = random.nextInt(6) + 1; int y1 = random.nextInt(12) + 1; g.drawLine(x, y, x + x1, y + y1); } // 随机产生70条干扰线,让图片更乱 for (int i = 0; i < 70; i++) { int x = random.nextInt(WIDTH - 1); int y = random.nextInt(HEIGHT - 1); int x1 = random.nextInt(12) + 1; int y1 = random.nextInt(6) + 1; g.drawLine(x, y, x - x1, y + y1); } String validateCode = getRandomString(); request.getSession().setAttribute(ConstantConfig.VALIDATE_CODE_KEY, validateCode.toLowerCase()); // request.getSession().setAttribute("validateCode", validateCode.toLowerCase()); // 将验证码画于图上 String tmp = ""; int[] pos = new int[2]; for(int i = 0, len = validateCode.length(); i < len; i++) { tmp = validateCode.substring(i, i + 1); g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110))); boolean odd = i % 2 != 0; pos[0] = 15 * i + (5 + i) + (odd ? -1 : 1); pos[1] = odd ? 21 : 18; g.drawString(tmp, pos[0], pos[1]); } g.dispose(); OutputStream out = null; try { out = response.getOutputStream(); JPEGImageEncoder imageEncoder = JPEGCodec.createJPEGEncoder(out); imageEncoder.encode(image); out.flush(); } catch(IOException ex) { log.error(ex.getMessage()); // ex.printStackTrace(); } finally { IOUtils.closeQuietly(out); }这样就实现了产生验证码的功能了,此类可以当做工具类来使用。然后在web,xml中配置此servlet,如下:
<servlet> <servlet-name>ValidateCode</servlet-name> <servlet-class>com.servlet.ValidateCodeGenerator</servlet-class> </servlet> <servlet-mapping> <servlet-name>ValidateCode</servlet-name> <url-pattern>/g/validateCode.jsp</url-pattern> </servlet-mapping>
配置后就可以在相应的jsp页面里使用<img src="/g/validateCode.jsp">来在页面上显示验证码。然而通常我们需要实现看不清点击更换验证码的作用,这个功能使用js写是最简单不过了,如下:
function changeCode(id) { var imgWrap = $(id), img = imgWrap.find('img'), src = img.attr('src'); if((idx = src.indexOf('?')) > -1) { src = src.substring(0, idx); } var imgSize = {width:img.width(),height:img.height()}; src = src + '?_' + (new Date()).getTime(); if($.support.cssFloat) { imgWrap.empty(); $('<img />').attr('src', src).attr('border', '0').width(imgSize.width).height(imgSize.height).appendTo(imgWrap); } else { img.attr('src', src); } }; function enterChangeCode(event) { var target = event.srcElement || event.target; if(event.keyCode == 13) { target.onclick(); } return false; }实现了验证码的切换功能以后在页面<div><a id="code" valign="absmiddle" title="看不清?请点击切换验证码。" href="javascript:void(0)" οnclick="changeCode('#code');return false;" hidefocus="hide"><img src="/g/validateCode.jsp" alt="" width="65" height="30" /></a></div>这样点击验证码就能切换了。这里面其实还有很多的细节,暂时就不去追究,等以后想到了再回来补。