`
esffor
  • 浏览: 1367717 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

图形验证码的java通用类

阅读更多

在应用程序中为防止系统被攻击程序自动访问,通常提供一个人眼容易识别,但程序很难识别的图形,图形内是随机产生的一些字符。为防止被攻击程序自动识别,字符通常会在位置和颜色上作随机处理。

为便于使用,本人用 java实现了一个生成随机字符图片的通用类,封装了生成过程的复杂性,能非常方便的使用。

实现类类名为RandomGraphic,它由一个静态工厂方法createInstance(int charCount)来创建对象实例,charCount指定图片中字符的个数,最多16个。

提供了两个方法来生成随机图片,一个方法String drawNumber(String graphicFormat,OutputStream out) 生成的图片中都是随机数字,由0-9组成。

另一个方法String drawAlpha(String graphicFormat,OutputStream out)生成的图片中都是随机字母,由a-z组成,生成的字符个数在工厂方法中指定。将数字和图片分开是因为有些数字和字母人眼看上去很难区分,反而影响用户输入。

graphicFormat为生成图片格式,取常量值GRAPHIC_JPEG 或 GRAPHIC_PNG

out用来输出生成的图片文件内容,可以是一个文件,或servlet中输出到客户端的流,以便于在页面显示。

 

下面给出原码和在servlet中的示例代码。

 

 

package net;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

import javax.imageio.ImageIO;

/**
 * 生成随机数字或字母串,以图像方式显示,用于人工识别,使程序很难识别。
 *  减小系统被程序自动攻击的可能性。
 *  生成的图形颜色由红、黑、蓝、紫4中随机组合而成,数字或字母垂直方向位置在
 *  一定范围内也是随机的,减少被程序自动识别的几率。
 *  由于数字的0,1,2易和字母的o,l,z混淆,使人眼难以识别,因此不生成数字
 *  和字母的混合串。
 *  生成的串字母统一用小写,串的最大长度为16。
 *
 * @version
 *  @Since
 * @See Also
 * @author lchen
 * Create Date 2005-12-16
 *
 */

public class RandomGraphic {
 //字符的高度和宽度,单位为像素
 private int wordHeight = 10;
 private int wordWidth = 15;
 //字符大小
 private int fontSize = 16;
 //最大字符串个数
 private  static final int MAX_CHARCOUNT = 16;
 
 //垂直方向起始位置
 private final int initypos = 5;
 
 
 //要生成的字符个数,由工厂方法得到
 private int charCount = 0;
 
 
 //颜色数组,绘制字串时随机选择一个
 private static final Color[] CHAR_COLOR = {Color.RED,Color.BLUE,Color.GREEN,Color.MAGENTA};
 
 //随机数生成器
 private Random r = new Random();
 
 /**
  * 生成图像的格式常量,JPEG格式,生成为文件时扩展名为.jpg;
  * 输出到页面时需要设置MIME type 为image/jpeg
  */
 public static String GRAPHIC_JPEG = "JPEG";
 /**
  * 生成图像的格式常量,PNG格式,生成为文件时扩展名为.png;
  * 输出到页面时需要设置MIME type 为image/png
  */
 public static String GRAPHIC_PNG = "PNG";
 
 
 
 //用工厂方法创建对象
 protected RandomGraphic(int charCount){
  this.charCount = charCount;
 }
 
 
 /**
  * 创建对象的工厂方法
  * @param charCount  要生成的字符个数,个数在1到16之间
  *
  * Return 返回RandomGraphic对象实例
  * @throws Exception  参数charCount错误时抛出
  */
 public static RandomGraphic createInstance(int charCount) throws Exception{
  if (charCount < 1 || charCount > MAX_CHARCOUNT){
   throw new Exception("Invalid parameter charCount,charCount should between in 1 and 16");
  }
  return new RandomGraphic(charCount);
 }
 
 
 /**
  * 随机生成一个数字串,并以图像方式绘制,绘制结果输出到流out中
  *
  * @param graphicFormat 设置生成的图像格式,值为GRAPHIC_JPEG或GRAPHIC_PNG
  * @param out  图像结果输出流
  * @return   随机生成的串的值
  * @throws IOException
  */
 public String drawNumber(String graphicFormat,OutputStream out) throws IOException{
//  随机生成的串的值
  String charValue = "";
  charValue = randNumber();
  return draw(charValue,graphicFormat,out);
  
 }

 /**
  * 随机生成一个字母串,并以图像方式绘制,绘制结果输出到流out中
  *
  * @param graphicFormat 设置生成的图像格式,值为GRAPHIC_JPEG或GRAPHIC_PNG
  * @param out  图像结果输出流
  * @return   随机生成的串的值
  * @throws IOException
  */
 public String drawAlpha(String graphicFormat,OutputStream out) throws IOException{
//  随机生成的串的值
  String charValue = "";
  charValue = randAlpha();
  return draw(charValue,graphicFormat,out);
  
 }


 
 
 
 /**
  * 以图像方式绘制字符串,绘制结果输出到流out中
  * @param charValue  要绘制的字符串
  * @param graphicFormat 设置生成的图像格式,值为GRAPHIC_JPEG或GRAPHIC_PNG
  * @param out  图像结果输出流
  * @return   随机生成的串的值
  * @throws IOException
  */
 protected String draw(String charValue,String graphicFormat,OutputStream out) throws IOException{
  
  //计算图像的宽度和高度
  int w = (charCount+2) * wordWidth;
  int h = wordHeight * 3;

  //创建内存图像区
  BufferedImage bi = new BufferedImage(w,h,BufferedImage.TYPE_3BYTE_BGR);
  Graphics2D g = bi.createGraphics();
  
  //设置背景色
  Color backColor = Color.WHITE;
  g.setBackground(backColor);
  g.fillRect(0,0,w,h);
  
  //设置font
  g.setFont(new Font(null,Font.BOLD,fontSize));
  //绘制charValue,每个字符颜色随机
  for(int i = 0; i < charCount; i++){
   String c = charValue.substring(i,i+1);
   Color color =  CHAR_COLOR[randomInt(0,CHAR_COLOR.length)];
   g.setColor(color);
   int xpos = (i+1) * wordWidth;
   //垂直方向上随机
   int ypos = randomInt(initypos+wordHeight,initypos+wordHeight*2);
   g.drawString(c,xpos,ypos);
  }
  g.dispose();
  bi.flush();
  // 输出到流
  ImageIO.write(bi,graphicFormat,out);
  
  return charValue;
 }
 
 
 
 
 protected String randNumber(){
  String charValue = "";
  //生成随机数字串
  for (int i = 0; i < charCount; i++){
   charValue += String.valueOf(randomInt(0,10));
  }
  return charValue;
 }
 
 
 private String randAlpha(){
  String charValue = "";
  //生成随机字母串
  for (int i = 0; i < charCount; i++){
   char c = (char) (randomInt(0,26)+'a');
   charValue += String.valueOf(c);
  }
  return charValue;
 }
 
 
 
 /**
  * 返回[from,to)之间的一个随机整数
  *
  * @param from 起始值
  * @param to 结束值
  * @return  [from,to)之间的一个随机整数
  */
 protected int randomInt(int from,int to){
  //Random r = new Random();
  return from+r.nextInt(to-from);
 }
 
 
 
 /**
  * @param args
  * @throws Exception
  */
 public static void main(String[] args) throws Exception {
 
  System.out.println(RandomGraphic.createInstance(5).drawAlpha(RandomGraphic.GRAPHIC_PNG,new FileOutputStream("c:/myimg.png")));

  
 }
 
}

RandomGraphic类原代码结束

 

在servlet中使用该类,将图片输出到客户端,在页面上就可显示随机图片

package net;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class RandImage extends HttpServlet {

 public RandImage() {
  super();
 
 }


 
 protected void doGet(HttpServletRequest req,HttpServletResponse res) throws IOException,ServletException{

//设置输出内容为图像,格式为jpeg
  res.setContentType("image/jpg");
  try {
//将内容输出到响应客户端对象的输出流中,生成的图片中包含6个字符

   String v = RandomGraphic.createInstance(6).drawAlpha(RandomGraphic.GRAPHIC_JPEG,res.getOutputStream());
//将字符串的值保留在session中,便于和用户手工输入的验证码比较,比较部分不是本文讨论重点,故略

   req.getSession().setAttribute("rv",v);
  } catch (Exception e) {
  
   e.printStackTrace();
  }
 
 }


}


需要在web.xml中配置该servlet

 <servlet>
   <servlet-name>RandImage</servlet-name>
   <servlet-class>net.RandImage</servlet-class>
  </servlet>
  
  <servlet-mapping>
   <servlet-name>RandImage</servlet-name>
   <url-pattern>/RandImage</url-pattern>
  </servlet-mapping>

 

然后在一个页面中用下面的代码来显示图片

<html>
<body>

验证码: <image src="RandImage" />


</body>
</html>

 

要增加图片的识别难度,还可以在draw方法中对图象进行一定程度变形回旋转处理,或者在图片中添加随机干扰线条,但要保证用人眼能比较容易识别。

 

分享到:
评论

相关推荐

    Java通用验证码及应用示例

    以下是对"Java通用验证码及应用示例"的详细解释: 1. **验证码的基本原理**: 验证码通常由随机生成的一串字符或数字组成,这些字符在显示时被扭曲、旋转或以其他方式混淆,以增加机器识别的难度。用户需要正确...

    Java Web网站通用图形验证码的实现.pdf

    Web网站的安全是开发人员要重点考虑因素之一,为提高系统安全性,普遍使用图形验证码技术。讨论了常用的网站验证码技术,提出了一种通用的实现方法。

    通用图形验证码识别程序(引擎)

    本程序可以识别多种图形验证码,正确率高,速度快,安全可靠。可供多种编程语言调用(vc、vb、delphi、java、c#、vb.net、asp、模拟精灵等),调用简单、灵活,可以通过传递文件名或图片数据流两种方式进行识别,提供...

    java验证码(关于用jdk去实现验证码)

    关于Java验证码的总结,在网上找到的,然后给整理了的,希望对你们有用

    原创-用Ajax制作带图形验证码的登录页面.

    ### 使用Ajax制作带图形验证码的登录页面 #### 一、前言 在现代Web开发中,安全性至关重要。其中,图形验证码作为一种防止自动化攻击的有效手段,被广泛应用于登录系统中。本文将详细介绍如何利用Ajax技术结合...

    Java识别系统源码合集13套源码(含携程自研的OCR项目、验证码、指纹、人脸、图形、证件、 百度通用文字识别等).zip

    Java识别系统源码合集13套源码(含携程自研的OCR项目、验证码、指纹、人脸、图形、证件、 百度通用文字识别、12306验证码识别等等).zip

    JAVA项目必用工具类

    这个工具类可能包含了生成随机图形验证码的功能,包括设置验证码长度、颜色、字体样式等,并能够将其保存到服务器端,同时返回给客户端显示的图片Base64编码或URL。 2. **PageUtils.java**:分页工具类。在处理大...

    java工具类

    Java中可以通过随机数生成、图片处理库(如Java2D)来创建图形验证码。通常包括生成随机数字或字母,添加干扰线,以及将验证码编码为图片等步骤。 5. 其他常用工具类: - `java.util.Collections`: 提供了对集合的...

    java开源包4

    JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java 穿越NAT方案 JSTUN.tar JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM...

    java开源包101

    JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java 穿越NAT方案 JSTUN.tar JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM...

    java开源包6

    JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java 穿越NAT方案 JSTUN.tar JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM...

    java开源包9

    JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java 穿越NAT方案 JSTUN.tar JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM...

    jmeter登陆验证码jar包

    在验证码场景中,SwingX可能用于构建用户界面,展示验证码图片,或者帮助开发者创建自定义的图形组件来处理验证码。 4. **logkit-2.0.jar**:LogKit是JMeter的日志处理库,用于记录测试过程中的信息,包括错误、...

    java开源包5

    JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java 穿越NAT方案 JSTUN.tar JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM...

    java开源包8

    JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java 穿越NAT方案 JSTUN.tar JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM...

    java开源包10

    JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java 穿越NAT方案 JSTUN.tar JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM...

    java开源包1

    JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java 穿越NAT方案 JSTUN.tar JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM...

    java开源包3

    JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java 穿越NAT方案 JSTUN.tar JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM...

    Java资源包01

    JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java 穿越NAT方案 JSTUN.tar JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM...

    Java中的3D图形技术及应用案例研究

    - **Java3D**:由Sun公司开发的高级3D图形API,除了Scenegraph API的通用优点外,还提供了多处理器和虚拟设备的支持,能够在OpenGL和DirectX环境下运行。不过,其运行效率相对较低。 - **JME (Java Monkey Engine)**...

Global site tag (gtag.js) - Google Analytics