图片验证码是在登录、注册中防止机器注册、灌水等的常用一种小技术。现在贴出我的一种实现代码,也是借鉴别人的。现在主要的java类如下:
public class RandImgCreater { private static final String CODE_LIST = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; private HttpServletResponse response = null; private static final int HEIGHT = 20; private static final int FONT_NUM = 4; private int width = 0; private int iNum = 0; private String codeList = ""; private boolean drawBgFlag = false; private int rBg = 0; private int gBg = 0; private int bBg = 0; public RandImgCreater(HttpServletResponse response) { this.response = response; this.width = 13 * FONT_NUM 12; this.iNum = FONT_NUM; this.codeList = CODE_LIST; } public RandImgCreater(HttpServletResponse response,int iNum,String codeList) { this.response = response; this.width = 13 * iNum 12; this.iNum = iNum; this.codeList = codeList; } public String createRandImage(){ BufferedImage image = new BufferedImage(width, HEIGHT, BufferedImage.TYPE_INT_RGB); Graphics g = image.getGraphics(); Random random = new Random(); if ( drawBgFlag ){ g.setColor(new Color(rBg,gBg,bBg)); g.fillRect(0, 0, width, HEIGHT); }else{ g.setColor(getRandColor(200, 250)); g.fillRect(0, 0, width, HEIGHT); for (int i = 0; i < 155; i ) { g.setColor(getRandColor(140, 200)); int x = random.nextInt(width); int y = random.nextInt(HEIGHT); int xl = random.nextInt(12); int yl = random.nextInt(12); g.drawLine(x, y, x xl, y yl); } } g.setFont(new Font("Times New Roman", Font.PLAIN, 18)); String sRand=""; for (int i=0;i int rand=random.nextInt(codeList.length()); String strRand=codeList.substring(rand,rand 1); sRand =strRand; g.setColor(new Color(20 random.nextInt(110),20 random.nextInt(110),20 random.nextInt(110))); g.drawString(strRand,13*i 6,16); }
g.dispose();
try{ ImageIO.write(image, "JPEG", response.getOutputStream()); }catch(IOException e){ } return sRand; } public void setBgColor(int r,int g,int b){ drawBgFlag = true; this.rBg = r; this.gBg = g; this.bBg = b; }
private Color getRandColor(int fc, int bc) { Random random = new Random(); 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); return new Color(r, g, b); } }
凭java类就可以生成相应的代码,建立一个img.jsp就可以调用:具体代码如下:
<%@ page import="com.register.img.RandImgCreater" %> http://www.w3.org/1999/xhtml"> <%@ page contentType="text/html;charset=GBK"%> <% out.clear(); response.setHeader("Pragma","No-cache"); response.setHeader("Cache-Control","no-cache"); response.setDateHeader("Expires", 0);
RandImgCreater rc = new RandImgCreater(response); String rand = rc.createRandImage();
//如果没有下面两句代码,将会出现getOutputStream() has already been called for this response异常 out.clear(); out = pageContext.pushBody(); session.setAttribute("rand",rand); %>
在这里提出几个问题,第一个,文中红线处,很重要,就这一句out.clear能有效防止在resin服务器下的乱码。没有这句,在tomcat服务器下是不存在问题的。还有下面红线句调用时能防止getOutputStream的异常错误。
第二个问题,就是在调用验证码的时候,不能在本页面调用,如果这样,得到的验证码总会比输出的验证码慢半拍,即得到的是上次的验证码。并且第一次得到的就是空的,会抛异常。这样的话,如果只是刷页面,并且不会得到验证码。所以最好的办法是另外建一个action,在action中进行验证。代码也很简单,如下:
<%
//得到验证码的值 String img=request.getParameter("code"); String rand=session.getAttribute("rand").toString();
if(img.equals(rand)==false) { %> alert("验证码错误") history.go(-1) <% }else{ %>alert("验证码正确")<%
}