生成验证码的几种方式
生成验证码的几种方式
1,在jsp页面中直接生成验证码
image.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); } // 将认证码存入SESSION session.setAttribute("rand", sRand); // 图象生效 g.dispose(); // 输出图象到页面 ImageIO.write(image, "JPEG", response.getOutputStream()); out.clear(); out = pageContext.pushBody(); %>
login.jsp源码(使用验证码的页面):
//使用验证码的页面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源码:
//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源码:
//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源码:
//测试页面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.java源码:
//RandomNumUtil.java package 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源码:
//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());// 取得随机字符串放入HttpSession return SUCCESS; } public void setInputStream(ByteArrayInputStream inputStream) { this.inputStream = inputStream; } public ByteArrayInputStream getInputStream() { return inputStream; } }
struts.xml配置:
//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中的表单源码:
//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>