生成图片验证码的几个页面以及JAVA文件:
?
MakeCertPic.java package cn.liuc.util; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.OutputStream; import java.util.Random; import javax.imageio.ImageIO; /** * @author dzy 生成验证码图片 */ public class MakeCertPic { // 验证码图片中可以出现的字符集,可根据需要修改 private char mapTable[] = { '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', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; /** * 功能:生成彩色验证码图片 参数width为生成图片的宽度,参数height为生成图片的高度,参数os为页面的输出流 */ public String getCertPic(int width, int height, OutputStream os) { if (width <= 0) width = 60; if (height <= 0) height = 20; BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 获取图形上下文 Graphics g = image.getGraphics(); // 设定背景色 g.setColor(new Color(0xDCDCDC)); g.fillRect(0, 0, width, height); // 画边框 g.setColor(Color.black); g.drawRect(0, 0, width - 1, height - 1); // 取随机产生的认证码 String strEnsure = ""; // 4代表4位验证码,如果要生成更多位的认证码,则加大数值 for (int i = 0; i < 4; ++i) { strEnsure += mapTable[(int) (mapTable.length * Math.random())]; } // 将认证码显示到图像中,如果要生成更多位的认证码,增加drawString语句 g.setColor(Color.black); g.setFont(new Font("Atlantic Inline", Font.PLAIN, 18)); String str = strEnsure.substring(0, 1); g.drawString(str, 8, 17); str = strEnsure.substring(1, 2); g.drawString(str, 20, 15); str = strEnsure.substring(2, 3); g.drawString(str, 35, 18); str = strEnsure.substring(3, 4); g.drawString(str, 45, 15); // 随机产生10个干扰点 Random rand = new Random(); for (int i = 0; i < 10; i++) { int x = rand.nextInt(width); int y = rand.nextInt(height); g.drawOval(x, y, 1, 1); } // 释放图形上下文 g.dispose(); try { // 输出图像到页面 ImageIO.write(image, "JPEG", os); } catch (IOException e) { return ""; } return strEnsure; } }
?makeCertPic.jsp
?
<%@page import="java.io.OutputStream"%>
<%@ page language="java" pageEncoding="UTF-8"%>
<jsp:useBean id="image" scope="page" class="cn.liuc.util.MakeCertPic" />
<%
OutputStream os = response.getOutputStream();
String str = image.getCertPic(0, 0, os);
// 将认证码存入SESSION
session.setAttribute("certCode", str);
out.clear();
out=pageContext.pushBody();
%>
?LoginPic.jsp
<%@ page contentType="text/html;charset=utf-8" %> <html> <head><title>登录页面</title></head> <body> <form action="loginCheck.jsp" method="post" > 验证码:<input type="text" name="certCode"/> <img src="makeCertPic.jsp"> <input type="submit" value="确定"/> </form> </body> </html>
?loginCheck.jsp
<%@ 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"> <% String certCode=request.getParameter("certCode"); if(certCode.equals((String)session.getAttribute("certCode"))) out.print("验证码输入正确"); else out.print("验证码输入错误"); %> <html> <head> <title>Insert title here</title> </head> <body> </body> </html>
?
红色部分(?makeCertPic.jsp的第十行)要格外注意,如果不加则会报java.lang.IllegalStateException: getOutputStream() has already been called for this response错误,
具体原因如下:
应用验证码时,都会用到字节流response.getOutputStream()来将验证码
?
输出,但是jsp页面自己最后会调用字符流JspWriter的out()方法将页面的内容输
?
出。通过查看servlet的API我们可以看到知道,在servlet中不能够同时利用这两
?
个流输出,解决办法将验证码写在servlet中或者在JSP的JAVA代码中加入
response.reset();
out.clear();
out=pageContext.pushBody();