当前位置: MXJAVA > JAVA开发 > 文章正文

利用jcaptcha生成自定义验证码

发表于 2007-08-28 | 阅读 781 views

  jcaptcha是一个开源的用来生成图形验证码的Java开源组件,使用起来也是非常的简单方便。不过,很多网友抱怨该组件默认的图片比较大,影响网页的美观。由于代码过于简单,以至于找不到地方修改。由于tycho(我正在开发的程序)也需要利用该组件生成验证码,所以简单地研究了一下。发现 jcapthca是非常强大的,不光是可以生成图片式的验证码,还可以生成声音式的(新浪就使用了双重验证码)。大家可以到这里下载,并导入到你的工程。

  若要利用jcaptcha生成自定义样式的验证码,首先需要为其创建一个验证码引擎,或者说验证码方案类。如下:

public class MyImageCaptchaEngine
      extends ListImageCaptchaEngine {
 protected void buildInitialFactories() {
  // 随机生成的字符
  WordGenerator wgen = new RandomWordGenerator(
      "abcdefghijklmnopqrstuvwxyz123456789");
  RandomRangeColorGenerator cgen =
       new RandomRangeColorGenerator(
         new int[] { 0, 100 }, new int[] { 0, 100 },
         new int[] { 0, 100 });
  // 文字显示的个数
  TextPaster textPaster = new RandomTextPaster(new Integer(6),
   new Integer(6), cgen, true);
  // 图片的大小
  BackgroundGenerator backgroundGenerator =
      new FunkyBackgroundGenerator(
       new Integer(150), new Integer(50));
  // 字体格式
  Font[] fontsList = new Font[] {
    new Font("Arial", 0, 10),
    new Font("Tahoma", 0, 10), new Font("Verdana", 0, 10), };
  // 文字的大小
  FontGenerator fontGenerator =
    new RandomFontGenerator(new Integer(15),
         new Integer(30), fontsList);    

  WordToImage wordToImage = new ComposedWordToImage(fontGenerator,
   backgroundGenerator, textPaster);
  this.addFactory(new GimpyFactory(wgen, wordToImage));
 }
}

  上面的自定义验证码引擎继承了ListImageCaptchaEngine类,那么它将会生成一个彩色的验证码。当然,你还可以继承其它的类来生成不同的验证码,如:声音格式的验证码。具体请参照官方网站。

  接下来,我们要为其定义一个单例类的全局对象,并在构造方法中注入我们的引擎。如下:

public class CaptchaServiceSingleton {
 private static DefaultManageableImageCaptchaService instance =
  new DefaultManageableImageCaptchaService(
  new FastHashMapCaptchaStore(),
  new MyImageCaptchaEngine(),
  180,
  100000,
  75000);    

 public static ImageCaptchaService getInstance() {
  return instance;
 }
}

  为什么要创建为单例的?当然,你可以不创建为单例类,但是你会发现,每次打开有验证码的画面时,验证码显示的都很慢,那是因为创建该对象的实例时,需要在内存中创建背景图像、描点、边框等等工作的原因。而创建一次后,图片框架就不需要再次创建了,以后每次调用该实例时,只是生成随机字符并嵌入图片中即可。

  接下来要做的就是,生成一个servlet,用来和前台页面交互,如下:

public class ImageCaptchaServlet extends HttpServlet {
 public void init(ServletConfig servletConfig)
    throws ServletException {
  super.init(servletConfig);    

 }
 // 复写doGet
 protected void doGet(HttpServletRequest httpServletRequest,
  HttpServletResponse httpServletResponse)
     throws ServletException, IOException {    

   byte[] captchaChallengeAsJpeg = null;
   ByteArrayOutputStream jpegOutputStream =
      new ByteArrayOutputStream();
   try {
    String captchaId =
       httpServletRequest.getSession().getId();
    BufferedImage challenge =
       CaptchaServiceSingleton.getInstance()
         .getImageChallengeForID(
            captchaId,httpServletRequest.getLocale());    

    JPEGImageEncoder jpegEncoder =
        JPEGCodec.createJPEGEncoder(jpegOutputStream);
    jpegEncoder.encode(challenge);
   } catch (IllegalArgumentException e) {
    httpServletResponse.sendError(
       HttpServletResponse.SC_NOT_FOUND);
    return;
   } catch (CaptchaServiceException e) {
    httpServletResponse.sendError(
        HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    return;
   }
   captchaChallengeAsJpeg = jpegOutputStream.toByteArray();
   httpServletResponse.setHeader("Cache-Control", "no-store");
   httpServletResponse.setHeader("Pragma", "no-cache");
   httpServletResponse.setDateHeader("Expires", 0);
   httpServletResponse.setContentType("image/jpeg");
   ServletOutputStream responseOutputStream =
        httpServletResponse.getOutputStream();
   responseOutputStream.write(captchaChallengeAsJpeg);
   responseOutputStream.flush();
   responseOutputStream.close();
 }
}

  配置这个servlet到web.xml文件,以使其生效。

 jcaptcha
 
    com.mxjava.tycho.servlet.captcha.ImageCaptchaServlet
 
 0

 jcaptcha
 /jcaptcha

  完成了以上部分后,就可以在前台页面写下用于显示验证码的代码:



   

  还记得我们在servlet里的配置吗?上面的上面的src="jcaptcha" 就是调用了上面的servlet。

  最后,也是最重要的一部分,就是在后台编写验证代码。

// 验证码是否正确flag
Boolean isResponseCorrect = Boolean.FALSE;
// 取session用来验证是否在同一session中
String captchaId = ServletActionContext.getRequest()
    .getSession().getId();
// 取前台输入的难证码
String response = ServletActionContext.getRequest()
    .getParameter("j_captcha_response");
try {
 // 取得验证对象,并检验session和输入验证码是否正确
 isResponseCorrect = CaptchaServiceSingleton.getInstance()
  .validateResponseForID(captchaId, response);
 // 如果不正确
 if (!isResponseCorrect) {
  // 输出错误信息
  super.addFieldError(Constants.REQ_ERR_MESSAGE, super
   .getText(Constants.VALIDATION_VERIFICATION_CODE_ERROR));
  return INPUT;
 }
} catch (CaptchaServiceException e) {
 // 根据你的需求做处理。
}

  至此,我们自定义的验证码就算完成了。值得注意的是,在修改图片大小时,要比图片上的文字大,不然会抛异常。

Del.icio.us Google书签 Digg Live Bookmark Technorati Furl Yahoo书签 Facebook 百度搜藏 新浪ViVi 365Key网摘 天极网摘 和讯网摘 博拉网 POCO网摘 添加到饭否 QQ书签 Digbuzz我挖网 关键字: ,
喜欢MXJAVA的文章,那就通过 RSS Feed 功能订阅阅读吧!

我要评论

*

* 绝不会泄露



返回首页 | 关于我们 | 联系我们 | 广告合作 | 友情链接 | 版权声明