论坛首页 Java企业应用论坛

servlet生产唯一图片验证码

浏览 10799 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (14) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-11-10   最后修改:2008-11-10
参考了几篇文章,写了个用servlet生产唯一验证码(改造了原作者代码,在此致谢,后附链接)。附件是可直接使用的工程。明天试用一个开源项目,可以比较方便的生成各种风格的验证码,甚至还有声音,比较有意思。第一次记录自己的学习,以后争取每天写一点。
===================================================
package com.stone.study.validate;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class ImgValidateServlet2 extends HttpServlet {
	private static int WIDTH = 90;
    private static int HEIGHT = 20;
    private static int LENGTH = 6;

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		 HttpSession session = request.getSession();

         response.setContentType("image/jpeg");

         ServletOutputStream sos = response.getOutputStream();

         //设置浏览器不要缓存此图片
         response.setHeader("Pragma","No-cache");
         response.setHeader("Cache-Control","no-cache");
         response.setDateHeader("Expires", 0);

         //创建内存图象并获得其图形上下文
         BufferedImage image = 
                new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); 

         Graphics g = image.getGraphics();

         //产生随机的认证码
         char [] rands = generateCheckCode();

         //产生图像
         drawBackground(g);

         drawRands(g,rands);

         //结束图像的绘制过程,完成图像
         g.dispose();

         //将图像输出到客户端
         ByteArrayOutputStream bos = new ByteArrayOutputStream();

         ImageIO.write(image, "JPEG", bos);

         byte [] buf = bos.toByteArray();

         response.setContentLength(buf.length);

         //下面的语句也可写成:bos.writeTo(sos);
         sos.write(buf);
         bos.close();
         sos.close();

         //将当前验证码存入到Session或者数据库中,下一个表单处理中验证客户端提交的验证码是否正确
         session.setAttribute("check_code",new String(rands));
	}

	private static char [] generateCheckCode()
    {
       //定义验证码的字符表
       String chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

       char [] rands = new char[LENGTH];
       for(int i=0; i<LENGTH; i++)

       {
          int rand = (int)(Math.random() * 36);
          rands[i] = chars.charAt(rand);
       }

       return rands;
    }
	
	   private void drawRands(Graphics g , char [] rands) 
       {
          g.setColor(Color.BLACK);
          g.setFont(new Font(null,Font.ITALIC|Font.BOLD,18));

          //在不同的高度上输出验证码的每个字符         
          g.drawString("" + rands[0],1,17);
          g.drawString("" + rands[1],16,15);
          g.drawString("" + rands[2],31,18);
          g.drawString("" + rands[3],46,16);
          g.drawString("" + rands[4],61,14);
          g.drawString("" + rands[5],76,19);

          System.out.println(rands);
       }

       private void drawBackground(Graphics g)

       {
           //画背景
          g.setColor(new Color(0xDCDCDC));
          g.fillRect(0, 0, WIDTH, HEIGHT);

          //随机产生120个干扰点
          for(int i=0; i<120; i++)

          {
             int x = (int)(Math.random() * WIDTH);

             int y = (int)(Math.random() * HEIGHT);

             int red = (int)(Math.random() * 255);

             int green = (int)(Math.random() * 255);

             int blue = (int)(Math.random() * 255);

             g.setColor(new Color(red,green,blue));        

             g.drawOval(x,y,1,0);

          }
          
          //加两条干扰线
          g.drawLine(0, 5, 90, 5);
          g.drawLine(0, 15, 90, 15);

       }

       public static void main(String args[]) {
    	   char[] chars = generateCheckCode();

    	   System.out.println(chars);
       }
}



代码出处:《深入体验Java Web开发内幕——核心基础》
   发表时间:2008-11-11   最后修改:2008-11-11
ImageIO.write(image, "JPEG", bos);   这么写是有BUG的, 可能导致你系统的流没有办法关闭。 你可以使用压力测试作作看。 虽然这样的代码很漂亮。 这是JAI的一个BUG导致的。 很恶心。

从使用方便角度, 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ      0/o 1/L 应该删除掉一个。
0 请登录后投票
   发表时间:2008-11-11   最后修改:2008-11-11
ImageIO.write(image, "JPEG", bos);  

这句效率极低...

给你个好的方法,参考下:
try{
    com.sun.jimi.core.Jimi.putImage("image/jpeg", image4, out);
}catch(Exception e){
    e.printStackTrace();
}
速度快,需要使用Sun提供的包,独立;
下载地址,不知道现在是否换有效:http://java.sun.com/products/jimi/
0 请登录后投票
   发表时间:2008-11-12   最后修改:2008-11-12
ImageIO支持NATIVE的IO的, 性能很不错了。
我们对JAI/IMAGEIO使用的比较多。 如果把NATIVE开启, 还能支持更多的图形格式。

JAI/IMAGEIO的成熟度似乎不是很好, 很多API的设计不合理, BUG也不少, 通用图形处理还是不错的。

如果想用更好的, 可以考虑JMAGIC了, 不过需要额外的NATIVE CODE安装。 换OS还是很恼火的。
0 请登录后投票
   发表时间:2008-11-18  
第一次发,且几乎是转发,得到这么多帮助,谢谢上面这些同学
0 请登录后投票
   发表时间:2008-12-02  
lz是学生,呵呵。。
0 请登录后投票
   发表时间:2008-12-02  
Jcaptcha..
0 请登录后投票
   发表时间:2008-12-18  
现在的验证应该都要应用Ajax实现。。
J2ee基本学完一遍,看到这些代码,虽然掌握理论明白怎么回事,不过很多awt类都不熟悉。如果叫我上手就写估计要折腾很久。新手跟有经验的差别吧
0 请登录后投票
   发表时间:2008-12-19   最后修改:2008-12-25
bohemia 写道
ImageIO.write(image, "JPEG", bos);  

这句效率极低...

给你个好的方法,参考下:
try{
    com.sun.jimi.core.Jimi.putImage("image/jpeg", image4, out);
}catch(Exception e){
    e.printStackTrace();
}
速度快,需要使用Sun提供的包,独立;
下载地址,不知道现在是否换有效:http://java.sun.com/products/jimi/

Jimi是一个操作图片的类库,它的原函数是image I/O。Jimi是以前Activated Intelligence的产品。该包sun是为依赖于Jimi的程序开发人员或运行在1.1.x版本Java平台的需要image I/O功能的应用程序提供的。Jimi支持的文件类型包括有:GIF, JPEG, TIFF, PNG, PICT, Photoshop, BMP, Targa, ICO, CUR, Sunraster, XBM, XPM, and PCX。不过并不支持个别类型的所有属性。
sun网站对于jimi的介绍,好像没讲到有jimi性能会高哦,好像是为低版本Java平台提供图片处理能力。而且接着就说到"For developers interested in image I/O on the Java 2 Platform the Java Image I/O API has been available since Java 2 version 1.4.0. "。
不过具体是不是如你所说没怎用过就不太清楚,还望高手再详说。
0 请登录后投票
   发表时间:2009-02-17  
qjmouse 写道
bohemia 写道
ImageIO.write(image, "JPEG", bos);  

这句效率极低...

给你个好的方法,参考下:
try{
    com.sun.jimi.core.Jimi.putImage("image/jpeg", image4, out);
}catch(Exception e){
    e.printStackTrace();
}
速度快,需要使用Sun提供的包,独立;
下载地址,不知道现在是否换有效:http://java.sun.com/products/jimi/

Jimi是一个操作图片的类库,它的原函数是image I/O。Jimi是以前Activated Intelligence的产品。该包sun是为依赖于Jimi的程序开发人员或运行在1.1.x版本Java平台的需要image I/O功能的应用程序提供的。Jimi支持的文件类型包括有:GIF, JPEG, TIFF, PNG, PICT, Photoshop, BMP, Targa, ICO, CUR, Sunraster, XBM, XPM, and PCX。不过并不支持个别类型的所有属性。
sun网站对于jimi的介绍,好像没讲到有jimi性能会高哦,好像是为低版本Java平台提供图片处理能力。而且接着就说到"For developers interested in image I/O on the Java 2 Platform the Java Image I/O API has been available since Java 2 version 1.4.0. "。
不过具体是不是如你所说没怎用过就不太清楚,还望高手再详说。

测试过,相差大概5倍左右;
ImageIO的性能是低一些的. 在Unix和Win下都测试过. 是jmi的性能高很多.

可以实际测试下,再决定用哪个. 满足需求才是主要的.
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics