J2EE验证码图片如何生成和点击刷新验证码
程序员文章站
2024-03-11 18:51:37
验证码图片生成步骤
创建bufferedimage对象。
获取bufferedimage的画笔,即调用getgraphics()方法获取graphics对象。
调用g...
验证码图片生成步骤
创建bufferedimage对象。
获取bufferedimage的画笔,即调用getgraphics()方法获取graphics对象。
调用graphics对象的setcolor()方法和fillrect()方法设置图片背景颜色。
调用graphics对象的setcolor()方法和drawline()方法设置图片干扰线。
调用bufferedimaged对象的setrgb()方法设置图片的噪点。
调用graphics对象的setcolor()方法、setfont()方法和drawstring()方法设置图片验证码。
因为验证码的图片的宽度和高度要根据网站的风格来确定的,所以字体的大小需要根据图片的宽度和高度来确定,用到了小小的技巧。
package util; import java.awt.color; import java.awt.font; import java.awt.graphics; import java.awt.image; import java.awt.image.bufferedimage; import java.io.bytearrayoutputstream; import java.io.ioexception; import java.util.random; import javax.imageio.imageio; public class verification { private static final string alphabet = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz1234567890"; /** * 生成一个宽为width, 高为height, 验证码为code的图片 * @param width 图片的宽 * @param height 图片的高 * @param code 验证码字符串 * @return 返回图片验证码 */ public static bufferedimage getimage(int width, int height, string code){ return getimage(width, height, code, 20); } /** * 生成一个宽为width, 高为height, 验证码为code的图片,图片中干扰线的条数为linecnt * @param width 图片的宽 * @param height 图片的高 * @param code 验证码字符串 * @param linecnt 干扰线的条数,建议为10条左右,可根据结果适当调整 * @return 返回图片验证码 */ public static bufferedimage getimage(int width, int height, string code, int linecnt){ return createimage(width, height, code, linecnt, 0.01); } /** * 生成一个宽为width, 高为height, 验证码为code的图片,图片中干扰线的条数为linecnt * 噪声比为noiserate,即图片中噪音像素点的百分比 * @param width 图片的宽 * @param height 图片的高 * @param code 验证码字符串 * @param linecnt 干扰线的条数,建议为10条左右,可根据结果适当调整 * @param noiserate 图片中噪音像素点占总像素的百分比 * @return 返回图片验证码 */ public static bufferedimage getimage(int width, int height, string code, int linecnt, double noiserate){ return createimage(width, height, code, linecnt, noiserate); } /** * * 生成一个宽为width, 高为height, 验证码为code的图片,图片中干扰线的条数为linecnt * 噪声比为noiserate,即图片中噪音像素点的百分比 * @param width 图片的宽 * @param height 图片的高 * @param code 验证码字符串 * @param linecnt 干扰线的条数,建议为10条左右,可根据结果适当调整 * @param noiserate 图片中噪音像素点占总像素的百分比 * @return 返回图片验证码 */ private static bufferedimage createimage(int width, int height, string code, int linecnt, double noiserate){ int fontwidth = ((int)(width * 0.8)) / code.length(); int fontheight = (int)(height * 0.7); //为了在任意的width和height下都能生成良好的验证码, //字体的大小为fontwdith何fontheight中的小者, int fontsize = math.min(fontwidth, fontheight); //drawstring时要用到 int paddingx = (int) (width * 0.1); int paddingy = height - (height - fontsize) / 2; //创建图像 bufferedimage buffimg = new bufferedimage(width, height, bufferedimage.type_int_rgb); //获得画笔 graphics g = buffimg.getgraphics(); //设置画笔的颜色 g.setcolor(getrandcolor(200, 255)); //然后填充一个矩形,即设置背景色 g.fillrect(0, 0, width, height); // 设置干扰线 for (int i = 0; i < linecnt; i++) { //随机获取干扰线的起点和终点 int xs = (int)(math.random() * width); int ys = (int)(math.random() * height); int xe = (int)(math.random() * width); int ye = (int)(math.random() * height); g.setcolor(getrandcolor(1, 255)); g.drawline(xs, ys, xe, ye); } // 添加噪点 int area = (int) (noiserate * width * height); for(int i=0; i<area; ++i){ int x = (int)(math.random() * width); int y = (int)(math.random() * height); buffimg.setrgb(x, y, (int)(math.random() * 255)); } //设置字体 font font = new font("ravie", font.plain, fontsize); g.setfont(font); for(int i=0; i<code.length(); ++i){ string ch = code.substring(i, i+1); g.setcolor(getrandcolor(1, 199)); g.drawstring(ch, paddingx + fontwidth * i, paddingy); } return buffimg; } /** * 获取随机的颜色,r,g,b的取值在l到r之间 * @param l 左区间 * @param r 右区间 * @return 返回随机颜色值 */ private static color getrandcolor(int l, int r){ if(l > 255) l = 255; if(r > 255) r = 255; if(l < 0) l = 0; if(r < 0) r = 0; int interval = r - l; int r = l + (int)(math.random() * interval); int g = l + (int)(math.random() * interval); int b = l + (int)(math.random() * interval); return new color(r, g, b); } /** * 随机生成若干个由大小写字母和数字组成的字符串 * @param len 随机生成len个字符 * @return 返回随机生成的若干个由大小写字母和数字组成的字符串 */ public static string getrandcode(int len){ string code = ""; for(int i=0; i<len; ++i){ int index = (int)(math.random() * alphabet.length()); code = code + alphabet.charat(index); } return code; } /** * 将图片转为byte数组 * @param image 图片 * @return 返回byte数组 * @throws ioexception */ public static byte[] getbytearray(bufferedimage image) throws ioexception{ bytearrayoutputstream baos = new bytearrayoutputstream(); imageio.write(image, "png", baos); return baos.tobytearray(); //bytearrayoutputstream 不需要close } }
使用验证码图片
在verificationcode.java这个servlet中调用上面的类生成验证码图片,然后将图片返回给客户端。
protected void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { httpsession session = request.getsession(); //随机生成字符串,并写入session string code = verification.getrandcode(4); session.setattribute("verification", code); bufferedimage image = util.verification.getimage(100,30, code, 5); response.setcontenttype("image/png"); outputstream out = response.getoutputstream(); out.write(util.verification.getbytearray(image)); out.flush(); out.close(); }
在index.jsp中设置验证码,用户点击验证码时,调用js代码请求服务器得到新的验证码。因为上面的那个生成验证码的servlet会被浏览器缓存,所以js代码中需要给该servlet一个随机的参数,这样浏览器就会向服务器发请求得到新的验证码,而不是去缓存中读取。
<%@page import="util.verification"%> <%@ page language="java" contenttype="text/html; charset=utf-8" pageencoding="utf-8"%> <!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title>insert title here</title> <script type="text/javascript"> function refreshcode(){ document.getelementbyid("verification").src= "/verificationcode/verificationcode?hehe="+math.random(); } </script> </head> <body> <form action="<%=request.getcontextpath()+"/checkverification" %>" method="post"> 验证码:<input type="text" name="submitverification"> <img id="verification" alt="" title="看不清点击刷新验证码" src="<%=request.getcontextpath()+"/verificationcode" %>" onclick="refreshcode()"><br> <input type="submit" name="submit" value="提交"> </form> </body> </html>
最后是在checkverification.java这个servlet中判断用户输入的验证码是否正确,为了方便用户,验证码一般都设置成大小写不敏感,所以要先转化为小写字母再比对。
protected void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { httpsession session = request.getsession(); string verification = (string)session.getattribute("verification"); string submitverification = request.getparameter("submitverification"); printwriter out = response.getwriter(); if(verification!=null && submitverification!=null){ if(verification.tolowercase().equals(submitverification.tolowercase())){ out.println("yes!!!"); } else{ out.println("no!!!"); } } else{ out.println("no!!!"); } session.removeattribute("verification");//防止用户重复提交表单 } /** * @see httpservlet#dopost(httpservletrequest request, httpservletresponse response) */ protected void dopost(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { // todo auto-generated method stub doget(request, response); }
最后运行的效果图如下
以上就是本文的全部内容,希望对大家的学习有所帮助。