一、说明:
此图片验证码生成的图片由大小写字母、数字、汉字组成,图片中字符大小被不同程度的缩放,或旋转。
二、常见的验证码:
1、文本验证码:由一组数字组成,以文本的方式返回。
2、简易的图片验证码:由数字和字母组成,以图片的方式返回。
3、加入干扰线的图片验证码:由数字、字母、干扰线组成,,以图片的方式返回。
4、单击验证码框时才生成并显示的验证码:除了是在单击验证码时,生成的验证码图片外,其他的和第三种一样。
三、示例代码:
1、IdentifyingCode.java类。此类主要用于生成验证码字符串、画干扰线。
在看此类之前应该先了解一下汉字的区位码:在国标GBK2312-80中规定,所有的国标汉字以及符号分配在一个94行、94列的方阵中,方阵的每一行称为一个“区”,编号为01区到94区,每一列称为一个“位”,编号01位到94位,方阵中的每一个汉字和符号所在的区号和位号组合在一起组成的4个阿拉伯数字就是他们的“区位码”。所有的汉字和符号所在的区分为4个组:
a、01区到15区:图形符号区,其中01区到09区为标准符号区,10区到15区为自定义字符区。
b、16区到55区:一级常用汉字区,包括2755个一级汉字。这40个区的汉字是按汉语拼音排序的,同音字按笔画顺序排序。
c、56区到87区:二级汉字区,包括3008个二级汉字,按部首排序。
d、88区到94区。
代码:
- import java.awt.Color;
- import java.awt.Graphics2D;
- import java.awt.geom.AffineTransform;
- import java.util.Random;
- /**
- * 验证码图片生成器
- *
- * @author WuZhengFei
- *
- */
- public class IdentifyingCode {
- /**
- * 验证码图片的宽度。
- */
- private int width = 80;
- /**
- * 验证码图片的高度。
- */
- private int height = 40;
- /**
- * 验证码的数量。
- */
- private Random random = new Random();
- public IdentifyingCode(){}
- /**
- * 生成随机颜色
- * @param fc 前景色
- * @param bc 背景色
- * @return Color对象,此Color对象是RGB形式的。
- */
- public Color getRandomColor(int fc, int bc) {
- if (fc > 255)
- fc = 200;
- 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);
- }
- /**
- * 绘制干扰线
- * @param g Graphics2D对象,用来绘制图像
- * @param nums 干扰线的条数
- */
- public void drawRandomLines(Graphics2D g ,int nums ){
- g.setColor(this.getRandomColor(160, 200)) ;
- for(int i=0 ; i<nums ; i++){
- int x1 = random.nextInt(width) ;
- int y1 = random.nextInt(height);
- int x2 = random.nextInt(12) ;
- int y2 = random.nextInt(12) ;
- g.drawLine(x1, y1, x2, y2) ;
- }
- }
- /**
- * 获取随机字符串,
- * 此函数可以产生由大小写字母,汉字,数字组成的字符串
- * @param length 随机字符串的长度
- * @return 随机字符串
- */
- public String drawRandomString(int length , Graphics2D g){
- StringBuffer strbuf = new StringBuffer() ;
- String temp = "" ;
- int itmp = 0 ;
- for(int i=0 ; i<length ; i++){
- switch(random.nextInt(5)){
- case 1: //生成A~Z的字母
- itmp = random.nextInt(26) + 65 ;
- temp = String.valueOf((char)itmp);
- break;
- case 2:
- itmp = random.nextInt(26) + 97 ;
- temp = String.valueOf((char)itmp);
- case 3: //生成汉字
- String[] rBase = {"0" , "1" , "2" , "3" , "4" , "5" , "6" , "7" ,
- "8" , "9" , "a" , "b" , "c" , "d" , "e" , "f" };
- int r1 = random.nextInt(3)+11 ; //生成第1位的区码
- String strR1 = rBase[r1] ; //生成11~14的随机数
- int r2 ; //生成第2位的区码
- if(r1 == 13)
- r2 = random.nextInt(7) ; //生成0~7的随机数
- else
- r2 = random.nextInt(16) ; //生成0~16的随机数
- String strR2 = rBase[r2] ;
- int r3 = random.nextInt(6) + 10 ; //生成第1位的位码
- String strR3 = rBase[r3] ;
- int r4 ; //生成第2位的位码
- if(r3 == 10)
- r4 = random.nextInt(15) + 1; //生成1~16的随机数
- else if(r3 == 15)
- r4 = random.nextInt(15) ; //生成0~15的随机数
- else
- r4 = random.nextInt(16) ; //生成0~16的随机数
- String strR4 = rBase[r4] ;
- //将生成的机内码转换成数字
- byte[] bytes = new byte[2] ;
- String strR12 = strR1 + strR2 ; //将生成的区码保存到字节数组的第1个元素中
- int tempLow = Integer.parseInt(strR12, 16) ;
- bytes[0] = (byte)tempLow;
- String strR34 = strR3 + strR4 ; //将生成的区码保存到字节数组的第2个元素中
- int tempHigh = Integer.parseInt(strR34, 16) ;
- bytes[1] = (byte)tempHigh;
- temp = new String(bytes); //根据字节数组生成汉字
- break;
- default:
- itmp = random.nextInt(10) + 48 ;
- temp = String.valueOf((char)itmp) ;
- break;
- }
- Color color = new Color(20+random.nextInt(20) , 20+random.nextInt(20) ,20+random.nextInt(20) );
- g.setColor(color) ;
- //想文字旋转一定的角度
- AffineTransform trans = new AffineTransform();
- trans.rotate(random.nextInt(45)*3.14/180, 15*i+8, 7) ;
- //缩放文字
- float scaleSize = random.nextFloat() + 0.8f ;
- if(scaleSize>1f)
- scaleSize = 1f ;
- trans.scale(scaleSize, scaleSize) ;
- g.setTransform(trans) ;
- g.drawString(temp, 15*i+18, 14) ;
- strbuf.append(temp) ;
- }
- g.dispose() ;
- return strbuf.toString() ;
- }
- public int getWidth() {
- return width;
- }
- public void setWidth(int width) {
- this.width = width;
- }
- public int getHeight() {
- return height;
- }
- public void setHeight(int height) {
- this.height = height;
- }
- }
2、PictureCheckCode.java类。此类是一个servlet。
代码:
- import java.awt.Font;
- import java.awt.Graphics2D;
- import java.awt.image.BufferedImage;
- import java.io.IOException;
- import javax.imageio.ImageIO;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- @SuppressWarnings("serial")
- public class PictureCheckCode extends HttpServlet {
- public PictureCheckCode() {
- super();
- }
- public void init() throws ServletException {
- super.init() ;
- }
- public void destroy() {
- super.destroy();
- }
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- doPost(request, response) ;
- }
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- //设置不缓存图片
- response.setHeader("Pragma", "No-cache");
- response.setHeader("Cache-Control", "No-cache");
- response.setDateHeader("Expires", 0) ;
- //指定生成的相应图片
- response.setContentType("image/jpeg") ;
- IdentifyingCode idCode = new IdentifyingCode();
- BufferedImage image =new BufferedImage(idCode.getWidth() , idCode.getHeight() , BufferedImage.TYPE_INT_BGR) ;
- Graphics2D g = image.createGraphics() ;
- //定义字体样式
- Font myFont = new Font("黑体" , Font.BOLD , 16) ;
- //设置字体
- g.setFont(myFont) ;
- g.setColor(idCode.getRandomColor(200 , 250)) ;
- //绘制背景
- g.fillRect(0, 0, idCode.getWidth() , idCode.getHeight()) ;
- g.setColor(idCode.getRandomColor(180, 200)) ;
- idCode.drawRandomLines(g, 160) ;
- idCode.drawRandomString(4, g) ;
- g.dispose() ;
- ImageIO.write(image, "JPEG", response.getOutputStream()) ;
- }
- }
3、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">
- <servlet>
- <servlet-name>PictureCheckCode</servlet-name>
- <servlet-class>com_2.PictureCheckCode</servlet-class>
- </servlet>
- <servlet-mapping>
- <servlet-name>PictureCheckCode</servlet-name>
- <url-pattern>/PictureCheckCode.jpeg</url-pattern>
- </servlet-mapping>
- <welcome-file-list>
- <welcome-file>index.jsp</welcome-file>
- </welcome-file-list>
- </web-app>
4、index.jsp
代码:
- <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <title>IdentifyingCode page</title>
- <script type="text/javascript">
- function myReload(){
- document.getElementById("createCheckCode").src=document.getElementById("createCheckCode").src + "?nocache="+new Date().getTime();
- }
- </script>
- </head>
- <body>
- <form action="PictureCheckCode" method="post">
- <input name="checkCode" type="text" id="checkCode" title="验证码区分大小写" maxlength="4">
- <img id="createCheckCode" src="PictureCheckCode.jpeg">
- <a href="#" onClick="myReload()">看不清,换一个</a>
- </form>
- </body>
- </html>
摘:http://wuzhengfei.iteye.com/blog/647754