package com.hoo.util; |
|
import java.awt.Color; |
import java.awt.Font; |
import java.awt.Graphics; |
import java.awt.image.BufferedImage; |
import java.util.Random; |
import javax.imageio.ImageIO; |
import javax.servlet.http.HttpServletRequest; |
import javax.servlet.http.HttpServletResponse; |
/** |
* <b>function:</b> 验证码生成工具类 |
* @project NetWorkService |
* @package com.hoo.util |
* @fileName ValidCodeUtils.java |
* @createDate 2010-8-3 下午03:05:50 |
* @author hoojo |
*/ |
@SuppressWarnings ( "unused" ) |
public class ValidCodeUtils { |
/********************************************************************* |
* 验证码宽度 |
*/ |
public static int WIDTH = 60 ; |
/*** |
* 验证码高度 |
*/ |
public static int HEIGHT = 20 ; |
/********************************************************************** |
* 验证码背景颜色COLOR_FC_BG 应当小于COLOR_BC_BG |
*/ |
public static int COLOR_FC_BG = 200 ; |
/*** |
* 验证码背景颜色COLOR_FC_BG 应当小于COLOR_BC_BG |
*/ |
public static int COLOR_BC_BG = 250 ; |
/********************************************************************** |
* 验证码背景干扰线颜色COLOR_FC_LINE 应当小于COLOR_BC_LINE |
*/ |
public static int COLOR_FC_LINE = 160 ; |
/*** |
* 验证码背景干扰线颜色COLOR_FC_LINE 应当小于COLOR_BC_LINE |
*/ |
public static int COLOR_BC_LINE = 200 ; |
/*************************************************************************** |
* 验证码颜色COLOR_FC_CODE 应当小于COLOR_BC_CODE |
*/ |
public static int COLOR_FC_CODE = 20 ; |
/*** |
* 验证码颜色COLOR_FC_CODE 应当小于COLOR_BC_CODE |
*/ |
public static int COLOR_BC_CODE = 170 ; |
/*************************************************************************** |
* 生成在指定范围内的颜色 |
* @param fc 范围fc color值 小于255 |
* @param bc 范围bc color值 小于255 |
* @return Color |
*/ |
private static Color getRandColor( int fc, int bc) { |
Random random = new Random(); |
if (fc < 0 ) |
fc = 0 ; |
if (bc < 0 ) |
bc = 1 ; |
if (fc > 255 ) |
fc = 255 ; |
if (bc > 255 ) |
bc = 255 ; |
if (bc == fc) |
bc += 10 ; |
int temp = 0 ; |
if (bc < fc) { |
temp = bc; |
bc = fc; |
fc = temp; |
} |
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); |
} |
/** |
* <b>function:</b> 生成图片方法 |
* @createDate 2010-8-3 下午03:06:22 |
* @author hoojo |
* @param request HttpServletRequest |
* @param response HttpServletResponse |
* @return boolean |
* @throws Exception |
*/ |
public static boolean getImage(HttpServletRequest request, HttpServletResponse response) throws Exception{ |
response.reset(); |
response.setContentType( "image/jpeg" ); |
// 设置页面不缓存 |
response.setHeader( "Pragma" , "No-cache" ); |
response.setHeader( "Cache-Control" , "no-cache" ); |
response.setDateHeader( "Expires" , 0 ); |
// 在内存中创建图象 |
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); |
// 获取图形上下文 |
Graphics img = image.getGraphics(); |
// 生成随机类 |
Random random = new Random(); |
// 设定背景色 |
img.setColor(getRandColor(COLOR_FC_BG, COLOR_BC_BG)); |
img.fillRect( 0 , 0 , WIDTH, HEIGHT); |
// 设定字体 |
img.setFont( new Font( "Times New Roman" , Font.PLAIN, 18 )); |
// 画边框 |
// g.setColor(new Color()); |
// g.drawRect(0,0,width-1,height-1); |
// 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到 |
img.setColor(getRandColor(COLOR_FC_LINE, COLOR_BC_LINE)); |
for ( int i = 0 ; i < 155 ; i++) { |
int x = random.nextInt(WIDTH); |
int y = random.nextInt(HEIGHT); |
int xl = random.nextInt( 12 ); |
int yl = random.nextInt( 12 ); |
img.drawLine(x, y, x + xl, y + yl); |
} |
// 取随机产生的认证码(4位数字) |
String codeValue = "" ; |
for ( int i = 0 ; i < 4 ; i++) { |
//String rand = String.valueOf(random.nextInt(10)); |
String rand = getRandomChar(); |
codeValue = codeValue.concat(rand); |
img.setFont(getRandomFont()); //随机字体 |
// 将认证码显示到图象中 |
img.setColor(getRandColor(COLOR_FC_CODE, COLOR_BC_CODE)); |
img.drawString(rand, 13 * i + 6 , 16 ); |
} |
request.getSession().setAttribute( "codeValue" , codeValue); |
// 图象生效 |
img.dispose(); |
// 输出图象到页面 |
return ImageIO.write(image, "JPEG" , response.getOutputStream()); |
} |
/** |
* 随机生成字符,含大写、小写、数字 |
* <b>function:</b> 功能 |
* @createDate 2010-8-23 上午10:33:55 |
* @author hoojo |
* @return |
*/ |
public static String getRandomChar() { |
int index = ( int ) Math.round(Math.random() * 2 ); |
String randChar = "" ; |
switch (index) { |
case 0 : //大写字符 |
randChar = String.valueOf(( char )Math.round(Math.random() * 25 + 65 )); |
break ; |
case 1 : //小写字符 |
randChar = String.valueOf(( char )Math.round(Math.random() * 25 + 97 )); |
break ; |
default : //数字 |
randChar = String.valueOf(Math.round(Math.random() * 9 )); |
break ; |
} |
return randChar; |
} |
/** |
* <b>function:</b> 随机生成字体、文字大小 |
* @createDate 2010-8-23 上午10:44:22 |
* @author hoojo |
* @return |
*/ |
public static Font getRandomFont() { |
String[] fonts = { "Georgia" , "Verdana" , "Arial" , "Tahoma" , "Time News Roman" , "Courier New" , "Arial Black" , "Quantzite" }; |
int fontIndex = ( int )Math.round(Math.random() * (fonts.length - 1 )); |
int fontSize = ( int ) Math.round(Math.random() * 4 + 16 ); |
return new Font(fonts[fontIndex], Font.PLAIN, fontSize); |
} |
} |
其中验证码的值是保存在session中:request.getSession().setAttribute( "codeValue" , codeValue); |
比较用户输入的值和session中的codeValue是否相等即可; |
下面是jsp页面调用servlet:ValidCodeServlet.java |
ValidCodeServlet中调用了上面的ValidCodeUtils 验证码生成工具类 |
package com.hoo.servlet; |
import java.io.IOException; |
import javax.servlet.ServletException; |
import javax.servlet.http.HttpServlet; |
import javax.servlet.http.HttpServletRequest; |
import javax.servlet.http.HttpServletResponse; |
import com.hoo.util.ValidCodeUtils; |
@SuppressWarnings ( "serial" ) |
public class ValidCodeServlet extends HttpServlet { |
public void doGet(HttpServletRequest request, HttpServletResponse response) |
throws ServletException, IOException { |
try { |
ValidCodeUtils.getImage(request, response); |
} catch (Exception e) { |
e.printStackTrace(); |
} |
} |
public void doPost(HttpServletRequest request, HttpServletResponse response) |
throws ServletException, IOException { |
doGet(request, response); |
} |
} |
|
jsp页面调用servlet方法即可 |
|
js:reloadValidCode方法 |
function reloadValidCode(o) { |
o.src = "${pageContext.request.contextPath }/validCodeServlet?timed=" + new Date().getMilliseconds(); |
} |
这里的 "timed=" + new Date().getMilliseconds();是需要防止IE缓存用的 |
html标签: |
<img src= "${pageContext.request.contextPath }/validCodeServlet" title= "看不清,点击刷新" onclick= "reloadValidCode(this)" /> |
直接跟Servlet名称配置的url即可,和web.xml配置对应。主要调用路径${pageContext.request.contextPath }/validCodeServlet这样会带上根目录,比较保险。 |
web.xml中validCodeServlet配置 |
<servlet> |
<servlet-name>validCodeServlet</servlet-name> |
<servlet- class >com.hoo.servlet.ValidCodeServlet</servlet- class > |
</servlet> |
<servlet-mapping> |
<servlet-name>validCodeServlet</servlet-name> |
<url-pattern>/validCodeServlet</url-pattern> |
</servlet-mapping> |
import java.awt.Color; |
import java.awt.Font; |
import java.awt.Graphics; |
import java.awt.image.BufferedImage; |
import java.io.IOException; |
import java.util.Date; |
import java.util.Random; |
import javax.imageio.ImageIO; |
import javax.servlet.ServletException; |
import javax.servlet.annotation.WebServlet; |
import javax.servlet.http.HttpServlet; |
import javax.servlet.http.HttpServletRequest; |
import javax.servlet.http.HttpServletResponse; |
/** |
* Servlet implementation class ValidateCode |
*/ |
@WebServlet ( "/ValidateCode" ) |
public class ValidateCode extends HttpServlet { |
private static final long serialVersionUID = 1L; |
|
/** |
* @see HttpServlet#HttpServlet() |
*/ |
public ValidateCode() { |
super (); |
// TODO Auto-generated constructor stub |
} |
/** |
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) |
*/ |
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { |
|
// 设置页面不缓存 |
response.setHeader( "Pragma" , "No-cache" ); |
response.setHeader( "Cache-Control" , "no-cache" ); |
response.setDateHeader( "Expires" , 0 ); |
// 设置图片的长宽 |
int width = 62 , height = 22 ; |
// ////// 创建内存图像 |
BufferedImage image = new BufferedImage(width, height, |
BufferedImage.TYPE_INT_RGB); |
// 获取图形上下文 |
Graphics g = image.createGraphics(); |
// 设定图像背景色(因为是做背景,所以偏淡) |
g.setColor(getRandColor( 180 , 250 )); |
g.fillRect( 0 , 0 , width, height); |
// 设置字体 |
g.setFont( new Font( "Times New Roman" , Font.PLAIN, 17 )); |
// /////设置默认生成4个验证码 |
int length = 4 ; |
java.util.Random rand = new Random(); // 设置随机种子 |
/* |
* if (request.getParameter("length") != null) { try { length = |
* Integer.parseInt(request.getParameter("length")); }catch |
* (NumberFormatException e) {} } |
*/ |
// 设置备选验证码:包括"a-z"和数字"0-9" |
String base = "abcdefghijklmnopqrstuvwxyz0123456789" ; |
int size = base.length(); |
StringBuffer str = new StringBuffer(); |
for ( int i = 0 ; i < length; i++) { |
int start = rand.nextInt(size); |
String tmpStr = base.substring(start, start + 1 ); |
str.append(tmpStr); |
// 生成随机颜色(因为是做前景,所以偏深) |
g.setColor(getRandColor( 10 , 150 )); |
// 将此字画到图片上 |
// g.drawString(str.toString(), 4, 17); |
g.drawString(tmpStr, 13 * i + 6 + rand.nextInt( 5 ), 14 + rand |
.nextInt( 6 )); |
} |
// 将认证码存入session |
request.getSession().setAttribute( "valiCode" , str.toString()); |
// 图象生效 |
g.dispose(); |
// 输出图象到页面 |
ImageIO.write(image, "JPEG" , response.getOutputStream()); |
} |
public void doPost(HttpServletRequest request, HttpServletResponse response) |
throws ServletException, IOException { |
this .doGet(request, response); |
} |
// 给定范围获得一个随机颜色 |
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); |
} |
} |