在使用Java开发Web应用程序特别是时,经常要用到验证码,特别是在注册新用户、登录时,大量地使用到验证码;
好的验证码可以有效的防止黑客使用机器人恶意登录,总之对于系统的安全是有很大影响的,以下为本人在平时开发项目的过程中总结出来的一个简单的验证码生成工具,原理很简单,只有一个类;
下面进入正题:
step1 在MyEclipse中新建一个web项目,在这里取名为ImageUtil,并在src目录下新建一个类 ImageUtil.java
step2 ImageUtil.java代码如下:
package util; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Map; import java.util.Random; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder; /** * 简单验证码生成工具 * ImageUtil, 用于生成验证码 * createImage方法返回一个Map类型,Map 的key是所生产的验证码的字符串, * Map的value是所生产的BufferImage类型的验证码; * getInputStream方法将 BufferImage转成InputStream类型; * @author CayZlh * @date 2013-11-26 */ public class ImageUtil { private static final char[] chars = {'0','1','2','3','4','5','6','7','8','9', 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q', 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H', 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}; private static final int SIZE = 4; //字符数 private static final int LINES = 12; //干扰线数量 private static final int WIDTH = 100; //生成的验证码图片的宽度 private static final int HEIGHT = 60; //生成的验证码图片的长度 private static final int FONT_SIZE = 35; //字体大小 public static Map<String, BufferedImage> createImage(){ //用户保存字符串 StringBuffer sb = new StringBuffer(); //BufferImage类型的验证码 BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); //获得画笔 Graphics g = image.getGraphics(); g.setColor(Color.LIGHT_GRAY); //设置背景色 g.fillRect(0, 0, WIDTH, HEIGHT);//将背景色填充到图片中 Random ran = new Random(); //获得一个Random对象 //画字符 for(int i=1; i<=SIZE; i++){ int r = ran.nextInt(chars.length); //得到一个随机的下标, chars 是保存着若干字符的char字符 g.setColor(getRandomColor()); //得到一个随机的颜色 g.setFont(new Font(null, Font.BOLD+Font.ITALIC, FONT_SIZE)); //设置字体大小 g.drawString(chars[r]+"", (i-1)*WIDTH/SIZE, (int)(HEIGHT*0.7)); //画字符 sb.append(chars[r]); } //画干扰线 for(int i=1; i<=LINES; i++){ g.setColor(getRandomColor()); //同样,干扰线也是用随机的颜色 g.drawLine(ran.nextInt(WIDTH), ran.nextInt(HEIGHT), ran.nextInt(WIDTH), ran.nextInt(HEIGHT));//随机设置干扰线的方向 } //将图片中的字符串保存为Map对象的key,BufferedImage保存为value Map<String, BufferedImage> map = new HashMap<String, BufferedImage>(); map.put(sb.toString(), image); return map; } /** * 获得一个随机的颜色 返回 Color对象 * @return */ private static Color getRandomColor() { Random ran = new Random(); Color color = new Color(ran.nextInt(256), ran.nextInt(256), ran.nextInt(256)); return color; } /** * 将 BufferImage转成InputStream类型 * @param image * @return * @throws IOException */ public static InputStream getInputStream(BufferedImage image) throws IOException{ ByteArrayOutputStream bos = new ByteArrayOutputStream(); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bos); encoder.encode(image); byte[] imageBts = bos.toByteArray(); InputStream in = new ByteArrayInputStream(imageBts); return in; } }
到此为止,ImageUtil工具类算是写完了。
接下来,就是去测试一下这个工具类的可用性了, 这部分我以Struts2为例展示一下效果,导入Struts2开发的jar包,新建Action类:
ImageDemoAction.java代码如下:
package action; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; import java.util.Map; import util.ImageUtil; public class ImageDemoAction { //stream result只能输出InputStream类型 private InputStream imageStream; public InputStream getImageStream() { return imageStream; } public void setImageStream(InputStream imageStream) { this.imageStream = imageStream; } public String execute() throws IOException{ //生成验证码 Map<String, BufferedImage> map = ImageUtil.createImage(); String key = map.keySet().iterator().next(); BufferedImage image = map.get(key); imageStream = ImageUtil.getInputStream(image); return "success"; } }
step3 添加Struts配置文件:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN" "http://struts.apache.org/dtds/struts-2.1.7.dtd"> <struts> <package name="demo" extends="struts-default" namespace="/demo"> <action name="image" class="action.ImageDemoAction"> <!-- inputName是固定写法, 目的是给这种类型的Result对象的inputName属性赋值. imageStream是Action里的输出属性名, 这个输出属性是InputStream类型的 --> <result type="stream"> <param name="inputName">imageStream</param> </result> </action> </package> </struts>
该注意的地方在注释部分也有给出
step4 配置web.xml:
web.xml的配置比较简单,就配置一个过滤器就行
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <filter> <filter-name>Struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter </filter-class> </filter> <filter-mapping> <filter-name>Struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
step5 添加demo.jsp页面(需要引入jquery文件, 这里使用 jquery-1.4.3.js 版本,个人觉得这个版本是最好用的):
<%@ 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>demo</title> <script type="text/javascript" src="js/jquery-1.4.3.js"></script> <script type="text/javascript"> $(function(){ //为图片绑定单击事件 $('#imageCode').click(function(){ //设置src属性为action的参数为当前时间,保证验证码点击之后可以变换 $(this).attr('src', 'demo/image.action?dt=' + new Date().getTime()); }); }); </script> </head> <body> <img src="demo/image.action" width="70" height="30" alt="验证码" title="点击更换" id="imageCode" style="cursor: pointer;" /> </body> </html>
step6 部署并启动服务器,在浏览器查看效果:
点击图片,可以更换图片。
项目整体结构如下:
这个工具可以直接应用到各种web项目中,如果不是用Struts,也可以使用servlet转发到页面中。
源代码下载地址 https://files.cnblogs.com/cayzlh/ImageUtil.zip
有表达和技术不足的地方,欢迎指正。。。