怎样生成验证码,看看这你就知道了
验证码操作在开发中是经常会使用到的,这里我为大家提供三种生成验证码方式,分别是:(1)jsp页面中直接生成验证码、(2)使用Servlet生成验证码、(3)、在struts2中实现验证码操作。下面就来看一下它们都是怎样实现的,这里提供完整的代码,并有详细的注释说明。
(1)、在jsp页面中直接生成验证码
//image.jsp<%@ page contentType="image/jpeg"import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*"pageEncoding="GBK"%><%!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);}%><%//设置页面不缓存response.setHeader("Pragma", "No-cache");response.setHeader("Cache-Control", "no-cache");response.setDateHeader("Expires", 0);// 在内存中创建图象// 通过这里可以修改图片大小int width = 85, height = 23;BufferedImage image = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);// 获取图形上下文// g相当于笔Graphics g = image.getGraphics();//生成随机类Random random = new Random();// 设定背景色g.setColor(getRandColor(200, 250));// 画一个实心的长方,作为北京g.fillRect(0, 0, width, height);//设定字体g.setFont(new Font("黑体", Font.PLAIN, 18));//画边框g.setColor(Color.BLUE);g.drawRect(0,0,width-1,height-1);// 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到g.setColor(getRandColor(160, 200));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);g.drawLine(x, y, x + xl, y + yl);}// 取随机产生的认证码(4位数字)//String rand = request.getParameter("rand");//rand = rand.substring(0,rand.indexOf("."));String sRand = "";// 如果要使用中文,必须定义字库,可以使用数组进行定义// 这里直接写中文会出乱码,必须将中文转换为unicode编码String[] str = { "A", "B", "C", "D", "E", "F", "G", "H", "J", "K","L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X","Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j","k", "m", "n", "p", "s", "t", "u", "v", "w", "x", "y", "z","1", "2", "3", "4", "5", "6", "7", "8", "9" };for (int i = 0; i < 5; i++) {String rand = str[random.nextInt(str.length)];sRand += rand;// 将认证码显示到图象中g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));//调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成g.drawString(rand, 16 * i + 6, 19);}// 将认证码存入SESSIONsession.setAttribute("rand", sRand);// 图象生效g.dispose();// 输出图象到页面ImageIO.write(image, "JPEG", response.getOutputStream());out.clear();out = pageContext.pushBody();%>//使用验证码的页面login.jsp<%@ page contentType="text/html" pageEncoding="GBK"%><html><head><title>登陆页面</title><script>function reloadImage() { document.getElementById('identity').src = 'image.jsp?ts=' + new Date().getTime();}</script></head><body><center><%// 乱码解决request.setCharacterEncoding("GBK");%><h1>登陆程序</h1><hr><%=request.getAttribute("info") != null ? request.getAttribute("info") : ""%><form action="check.jsp" method="post">用户ID:<input type="text" name="mid"><br>密 码:<input type="password" name="password"><br>验证码:<input type="text" name="code" maxlength="5" size="5"><img src="image.jsp" id="identity" onclick="reloadImage()" title="看不清,点击换一张"><br><input type="submit" value="登陆"><input type="reset" value="重置"></form></center></body></html>
效果如下:
(2)、使用Servlet生成验证码
//IdentityServlet.java代码如下:package com.helloweenvsfei.servlet;import java.awt.Color;import java.awt.Font;import java.awt.Graphics2D;import java.awt.image.BufferedImage;import java.io.IOException;import java.util.Random;import javax.servlet.ServletException;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.sun.image.codec.jpeg.JPEGCodec;import com.sun.image.codec.jpeg.JPEGImageEncoder;public class IdentityServlet extends HttpServlet {/** * */private static final long serialVersionUID = -479885884254942306L;public static final char[] CHARS = { '2', '3', '4', '5', '6', '7', '8','9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M','N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };public static Random random = new Random();public static String getRandomString() {StringBuffer buffer = new StringBuffer();for (int i = 0; i < 6; i++) {buffer.append(CHARS[random.nextInt(CHARS.length)]);}return buffer.toString();}public static Color getRandomColor() {return new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255));}public static Color getReverseColor(Color c) {return new Color(255 - c.getRed(), 255 - c.getGreen(), 255 - c.getBlue());}public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("image/jpeg");String randomString = getRandomString();request.getSession(true).setAttribute("randomString", randomString);int width = 100;int height = 30;Color color = getRandomColor();Color reverse = getReverseColor(color);BufferedImage bi = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);Graphics2D g = bi.createGraphics();g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 16));g.setColor(color);g.fillRect(0, 0, width, height);g.setColor(reverse);g.drawString(randomString, 18, 20);for (int i = 0, n = random.nextInt(100); i < n; i++) {g.drawRect(random.nextInt(width), random.nextInt(height), 1, 1);}// 转成JPEG格式ServletOutputStream out = response.getOutputStream();JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);encoder.encode(bi);out.flush();}public static void main(String[] args) {System.out.println(getRandomString());}}//Web.xml的配置为:<servlet> <servlet-name>IdentityServlet</servlet-name> <servlet-class>com.helloweenvsfei.servlet.IdentityServlet</servlet-class></servlet><servlet-mapping> <servlet-name>IdentityServlet</servlet-name> <url-pattern>/servlet/IdentityServlet</url-pattern></servlet-mapping>//测试页面identity.html为:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title>identity.html</title><meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="this is my page"><meta http-equiv="content-type" content="text/html; charset=GB18030"><!--<link rel="stylesheet" type="text/css" href="./styles.css">--></head><body><script>function reloadImage() {document.getElementById('btn').disabled = true;document.getElementById('identity').src='servlet/IdentityServlet?ts=' + new Date().getTime();}</script><img src="servlet/IdentityServlet" id="identity" onload="btn.disabled = false; " /><input type=button value=" 换个图片 " onclick="reloadImage()" id="btn"></body></html>
(3)、在Struts2应用中生成验证码
//RandomNumUtil.javapackage org.ml.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.util.Random;import javax.imageio.ImageIO;import javax.imageio.stream.ImageOutputStream;public class RandomNumUtil {public static final char[] CHARS = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M','N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z','2', '3', '4', '5', '6', '7', '8','9','a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm','n', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}; private ByteArrayInputStream image;// 图像private String str;// 验证码/** * 构造方法调用初始化属性方法 */private RandomNumUtil() {init();}/** * 取得RandomNumUtil实例 */public static RandomNumUtil Instance() {return new RandomNumUtil();}/** * 取得验证码图片 */public ByteArrayInputStream getImage() {return this.image;}/** * 取得图片的验证码 */public String getString() {return this.str;}/** * 初始化属性否具体方法 */private void init() {// 在内存中创建图象int width = 85, height = 18;//设置图形的高度和宽度,以及RGB类型BufferedImage image = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);// 获取图形上下文Graphics g = image.getGraphics();// 生成随机类Random random = new Random();// 设定背景色g.setColor(getRandColor(200, 250));g.fillRect(0, 0, width, height);// 设定字体g.setFont(new Font("Times New Roman", Font.PLAIN, 18));// 随机产生255条干扰线,使图象中的认证码不易被其它程序探测到g.setColor(getRandColor(160, 200));for (int i = 0; i < 255; i++) {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);}// 取随机产生的认证码(6位数字)StringBuffer sRand = new StringBuffer(); for (int i = 0; i < 6; i++) {String rand = String.valueOf(CHARS[random.nextInt(CHARS.length-1)]);//从字符数组中随机产生一个字符sRand.append(rand); // 将认证码显示到图象中g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));// 调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成g.drawString(rand, 13 * i + 6, 17);}// 赋值验证码this.str = sRand.toString();// 图象生效g.dispose();//下面将生成的图形转变为图片ByteArrayOutputStream output = new ByteArrayOutputStream(); ByteArrayInputStream input = null;try {ImageOutputStream imageOut = ImageIO.createImageOutputStream(output);ImageIO.write(image, "JPEG", imageOut);//将图像按JPEG格式写入到imageOut中,即存入到output的字节流中imageOut.close();//关闭写入流input = new ByteArrayInputStream(output.toByteArray());//input读取output中的图像信息} catch (Exception e) {System.out.println("验证码图片产生出现错误:" + e.toString());}this.image = input;/* 赋值图像 */} /* * 给定范围获得随机颜色 */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);}}//RandomAction.java的代码:package org.ml.action;import java.io.ByteArrayInputStream;import org.ml.util.RandomNumUtil;import com.opensymphony.xwork2.ActionContext;import com.opensymphony.xwork2.ActionSupport;@SuppressWarnings("serial")public class RandomAction extends ActionSupport {private ByteArrayInputStream inputStream;public String execute() throws Exception {RandomNumUtil rdnu = RandomNumUtil.Instance();//取得随机验证码产生类的对象this.setInputStream(rdnu.getImage());// 取得带有随机字符串的图片ActionContext.getContext().getSession().put("random", rdnu.getString());// 取得随机字符串放入HttpSessionreturn SUCCESS;}public void setInputStream(ByteArrayInputStream inputStream) {this.inputStream = inputStream;}public ByteArrayInputStream getInputStream() {return inputStream;}}//struts.xml配置为:<!-- Random验证码 --><action name="rand" class="org.ml.action.RandomAction"> <result type="stream" name="success"><param name="contentType">image/JPEG</param><param name="inputName">inputStream</param> </result></action>
//HTML中的表单代码为:<tr height="35" > <td width="14%" class="top_hui_text"> <span class="login_txt"> 验证码: </span> </td> <td colspan="2" class="top_hui_text"> <input type="text" name="rand" id="rand" size="6" maxlength="6"> <script type="text/javascript"> function changeValidateCode(obj) { //获取当前的时间作为参数,无具体意义 var timenow = new Date().getTime(); //每次请求需要一个不同的参数,否则可能会返回同样的验证码 //这和浏览器的缓存机制有关系,也可以把页面设置为不缓存,这样就不用这个参数了。 obj.src="rand.action?d="+timenow; } </script> <img src="rand.action" title="点击图片刷新验证码" onclick="changeValidateCode(this)" height="22" width="80" /> </td> </tr>
以上使用了三种方式进行验证码的生成,如果需要的话,可以仿照这个来进行开发。