`
gogole_09
  • 浏览: 205566 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

超棒的验证码生成组件---Jcaptcha

阅读更多

   最近由于Springside3的发布,也来凑热闹学习学习, 毕竟是国人的开源项目。 由于之前仅仅有听过,但是没有具体研究,所以算比较落后的。 不过这个项目确实是非常好的项目, 从中可以了解不少新新东西( - 可能是我太过时了!)

 

   正好我最近需要给老婆开发个小东西,其中有用到验证码的生成, 在Springside里面找到个非常棒的组件---Jcaptcha

 

   Springside对其做了封装,而且其官方的文档看起来也比较费力。所以自己琢磨了半天,才学会一个小的demo。

  这里发上来, 希望能帮助有需要的人, (本人在网上找了不少资料, 所给的素材不是不全就是说的不太明白)

 

    OK,开始,我先从一个示例开始。

 

    首先来看看示例的目录结构:

    
       

 

       在Jcaptcha的官方文档中有一个 5分钟快速入门的文章, 是介绍快速开发的文章。 有兴趣的可以去上面看看。

      这里我发上我的源代码:

 

 

     web.xml中:

 

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>

	<servlet>
		<servlet-name>jcaptcha</servlet-name>
		<servlet-class>com.ivan.zhang.servlet.ImageCaptchaServlet</servlet-class>
		<load-on-startup>0</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>jcaptcha</servlet-name>
		<url-pattern>/jcaptcha</url-pattern>
	</servlet-mapping> 
</web-app>

 

    再需要一个服务类,用来产生Image Service类:

 

package com.ivan.zhang.servlet;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

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

import com.ivan.zhang.CaptchaServiceSingleton;
import com.octo.captcha.service.CaptchaServiceException;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public class ImageCaptchaServlet extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public void init(ServletConfig servletConfig) throws ServletException {
		super.init(servletConfig);
	}

	protected void doGet(HttpServletRequest httpServletRequest,
			HttpServletResponse httpServletResponse) throws ServletException,
			IOException {

		byte[] captchaChallengeAsJpeg = null;
		// the output stream to render the captcha image as jpeg into
		ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
		try {
			// get the session id that will identify the generated captcha.
			// the same id must be used to validate the response, the session id
			// is a good candidate!
			String captchaId = httpServletRequest.getSession().getId();
			// call the ImageCaptchaService getChallenge method
			BufferedImage challenge = CaptchaServiceSingleton.getInstance()
					.getImageChallengeForID(captchaId,
							httpServletRequest.getLocale());

			// a jpeg encoder
			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();
		// flush it in the response
		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();
	}
}
 

   OK,后台的类写完了, 现在我们来看看前台页面的编写:

 

   index.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="sample.jsp">
	<img src="jcaptcha">
	<input type='text' name='j_captcha_response' value=''>
</form>
</body>
</html>

 

    sample.jsp: (用来验证的页面 )

 

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="UTF-8"%>
<%@page import="com.octo.captcha.service.CaptchaServiceException"%>
<%@page import="com.ivan.zhang.CaptchaServiceSingleton"%>
<%
	Boolean isResponseCorrect = Boolean.FALSE;
	//remenber that we need an id to validate!
	String captchaId = request.getSession().getId();
	//retrieve the response
	String responsestr = request.getParameter("j_captcha_response");
	// Call the Service method
	try {
		isResponseCorrect = CaptchaServiceSingleton.getInstance().validateResponseForID(captchaId, responsestr);
		if(isResponseCorrect){
			
		}else{
			out.print("It's worng......");
		}
	} catch (CaptchaServiceException e) {
		//should not happen, may be thrown if the id is not valid
	}
%>
 

   这样,我们的第一个版本出来了, 我们来看看效果:

   

 

  我们看到, 虽然生成了验证码,但是这样的图片给人非常不友好的感觉,  所以我参考Springside中的一样,自己给他设定产生图片的样式:

   要实现自定义样式,我们需要一下2个步骤: 

   1. 告诉Jcaptcha 我要的样式是什么样子.

   2. 在提交后,利用我们自己的样式来产生图片.

 

  所以,我们改动一下 :

    新加一个类GmailEngine.java(直接拿至Springside ,非常感谢白衣的共享,让我们这样的菜鸟学到很多东西.)

   

 

  其中代码如下:

 

package com.ivan.zhang.servlet;

import java.awt.Color;
import java.awt.Font;
import java.awt.image.ImageFilter;

import com.octo.captcha.component.image.backgroundgenerator.BackgroundGenerator;
import com.octo.captcha.component.image.backgroundgenerator.UniColorBackgroundGenerator;
import com.octo.captcha.component.image.color.RandomListColorGenerator;
import com.octo.captcha.component.image.deformation.ImageDeformation;
import com.octo.captcha.component.image.deformation.ImageDeformationByFilters;
import com.octo.captcha.component.image.fontgenerator.FontGenerator;
import com.octo.captcha.component.image.fontgenerator.RandomFontGenerator;
import com.octo.captcha.component.image.textpaster.DecoratedRandomTextPaster;
import com.octo.captcha.component.image.textpaster.TextPaster;
import com.octo.captcha.component.image.textpaster.textdecorator.TextDecorator;
import com.octo.captcha.component.image.wordtoimage.DeformedComposedWordToImage;
import com.octo.captcha.component.image.wordtoimage.WordToImage;
import com.octo.captcha.component.word.FileDictionary;
import com.octo.captcha.component.word.wordgenerator.ComposeDictionaryWordGenerator;
import com.octo.captcha.component.word.wordgenerator.WordGenerator;
import com.octo.captcha.engine.image.ListImageCaptchaEngine;
import com.octo.captcha.image.gimpy.GimpyFactory;

/**
 * 仿照JCaptcha2.0编写GMail验证码样式的图片引擎.
 * 
 * @author calvin
 */
public class GMailEngine extends ListImageCaptchaEngine {
	@Override
	protected void buildInitialFactories() {
		int minWordLength = 4;
		int maxWordLength = 5;
		int fontSize = 50;
		int imageWidth = 250;
		int imageHeight = 100;

		//word generator
		WordGenerator dictionnaryWords = new ComposeDictionaryWordGenerator(new FileDictionary("toddlist"));

		//word2image components
		TextPaster randomPaster = new DecoratedRandomTextPaster(minWordLength, maxWordLength,
				new RandomListColorGenerator(new Color[] { new Color(23, 170, 27), new Color(220, 34, 11),
						new Color(23, 67, 172) }), new TextDecorator[] {});
		BackgroundGenerator background = new UniColorBackgroundGenerator(imageWidth, imageHeight, Color.white);
		FontGenerator font = new RandomFontGenerator(fontSize, fontSize, new Font[] {
				new Font("nyala", Font.BOLD, fontSize), new Font("Bell MT", Font.PLAIN, fontSize),
				new Font("Credit valley", Font.BOLD, fontSize) });

		ImageDeformation postDef = new ImageDeformationByFilters(new ImageFilter[] {});
		ImageDeformation backDef = new ImageDeformationByFilters(new ImageFilter[] {});
		ImageDeformation textDef = new ImageDeformationByFilters(new ImageFilter[] {});

		WordToImage word2image = new DeformedComposedWordToImage(font, background, randomPaster, backDef, textDef,
				postDef);
		addFactory(new GimpyFactory(dictionnaryWords, word2image));
	}

}
 

   如果有玩过Swing的兄弟,应该会很好理解上面的代码。

 

   继续,我们有了自己的样式类, 接下来我们就要告诉servlet我们需要用哪个样式生成图片。

   就有如下,将CaptchaServiceSingleton类修改一下:

 

package com.ivan.zhang;

import com.ivan.zhang.servlet.GMailEngine;
import com.octo.captcha.engine.GenericCaptchaEngine;
import com.octo.captcha.service.CaptchaService;
import com.octo.captcha.service.captchastore.FastHashMapCaptchaStore;
import com.octo.captcha.service.image.DefaultManageableImageCaptchaService;
import com.octo.captcha.service.image.ImageCaptchaService;

/**
 * 按照官方的做法: 一定为单例
 * @author Administrator
 *
 */
public class CaptchaServiceSingleton {
	 private static ImageCaptchaService instance = new DefaultManageableImageCaptchaService(
			   new FastHashMapCaptchaStore(), new GMailEngine(), 180,
			   100000 , 75000);
    public static ImageCaptchaService getInstance(){
        return instance;
    }
}
 

    同样的,修改一下Servlet类:

 

    改动如下:

 

package com.ivan.zhang.servlet;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

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

import com.ivan.zhang.CaptchaServiceSingleton;
import com.octo.captcha.service.CaptchaServiceException;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public class ImageCaptchaServlet extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public void init(ServletConfig servletConfig) throws ServletException {
		super.init(servletConfig);
	}

	protected void doGet(HttpServletRequest httpServletRequest,
			HttpServletResponse httpServletResponse) throws ServletException,
			IOException {
		genernateCaptchaImage(httpServletRequest, httpServletResponse);
	}
	
	
	/**
	 * 生成验证码图片.
	 */
	private void genernateCaptchaImage(final HttpServletRequest request, final HttpServletResponse response)
			throws IOException {
		response.setHeader("Cache-Control", "no-store");
		response.setHeader("Pragma", "no-cache");
		response.setDateHeader("Expires", 0);
		response.setContentType("image/jpeg");
		ServletOutputStream out = response.getOutputStream();
		try {
			String captchaId = request.getSession(true).getId();
			BufferedImage challenge = (BufferedImage)  CaptchaServiceSingleton.getInstance().getChallengeForID(captchaId, request.getLocale());
			ImageIO.write(challenge, "jpg", out);
			out.flush();
		} catch (CaptchaServiceException e) {
		} finally {
			out.close();
		}
	}
}

 

  OK, 这样我们产生的图片样式就会好看多了。 不相信?  OK, 非要上图才有人相信。

    截图如下:



    再来一下刷新:

   

 

    OK, 先写到这,希望对有需要的人有帮助。

  如果有人懒得敲代码,我这里附上我的工程源代码, 不过我还是觉得,咱弄技术的人, 就得把键盘当筷子, 你见过非常饿,但不想拿筷子的人吗?(别说老外用叉子……)

 

  • 大小: 23.3 KB
  • 大小: 10.4 KB
  • 大小: 6.8 KB
  • 大小: 10.3 KB
  • 大小: 7.2 KB
  • 大小: 7.1 KB
分享到:
评论
36 楼 osacar 2010-08-17  
自己搞了一上午都没搞出来。我是和struts2一起用的。看看楼主这文章有没有先。
35 楼 youanyyou 2010-05-26  
没有加干扰线
34 楼 rain2005 2010-05-26  
大家知道kaptcha不,就是改进了的Jcaptcha,我用了这个。
33 楼 sdh5724 2010-05-26  
这东西性能超级烂, 烂到极点。  不过, 我是把他的代码彻底的修改了了, 其实更好听的说法是, 我参考了他的实现而已~
32 楼 hatedance 2010-05-26  
一般的验证码都是考验ocr。
其实完全可以有很多其他的思路,比如随机给出一张人脸,回答是哪种表情。
总之,只要AI做不到的事情就可以了,不要太多。
31 楼 ganky 2010-05-26  
正因为非常饿才不用筷子……暂时没这闲情品味,代码我收下了~~对我这类新人还是很有用的,谢谢
30 楼 jushi1988 2010-03-19  
学习了..
29 楼 Mrpublic 2010-03-19  
Lunatica 写道
验证码主要是为了防止机器人对其辨识,如果就将图片修改的很容易辨认就意义不大了


我一直就搞不懂 驗證碼 有啥用呢?
能不能說具體一點呢? 為什麽多一個這個東西,沒感到它有什麽作用 就是多一次輸入而已呀?
28 楼 sdh5724 2010-03-19  
性能极度的垃圾, 非常垃圾!
27 楼 yuanyong 2010-03-19  
不觉得很棒
26 楼 benbenming 2010-03-19  
东东还是不错的。只不过不太喜欢使用一个类而加载一个包。
25 楼 魔力猫咪 2010-01-28  
大家试试我BAC框架中的验证码组件,和这个比如何
地址http://code.google.com/p/basicaidedcomponent/
24 楼 azhoujun 2010-01-28  
很不错的验证码组件。可以自己修改engine,增加背景图片等,也可以扭曲文字,很方便的。官网上有很多实现样例。
23 楼 Javac_MyLife 2010-01-21  
前一阵子想用这个来着 不过看了看 还是自己写了一个servlet用来生成  貌似LZ的这个也没有看出什么亮点  指教。。。
22 楼 LifeFree 2010-01-15  
效果很一般啊,使用也麻烦。推荐还是用别的吧。
如果接受这种简单效果的验证码,不如自己简单写个类,实现也很简单。
不过验证码确属防君子不防小人,有研究表明现在的图像识别软件其实和人眼基本是一样厉害,像yahoo那种复杂的验证码基本上人眼和软件的识别率都是30%多。
21 楼 chan.d 2010-01-14  
标题党..
20 楼 linginfanta 2010-01-14  
一张图片而以。
19 楼 zhoujypp 2010-01-14  
觉得粘连性还是不太够。。貌似也缺少扭转弯曲改变角度等效果
18 楼 aaronluo 2010-01-14  
那不知道有没有更好的Java解决方案呢?目前一个项目也考虑要不要用
17 楼 hongjn 2010-01-13  
楼主刷屏  

相关推荐

    效果超棒的Webgl模型-手袋

    这个“效果超棒的Webgl模型-手袋”很可能是一个包含高质量3D模型的手袋展示项目,利用WebGL技术在网页上实现交互式、动态的3D视图。 WebGL的核心是它允许开发者直接在浏览器中处理顶点、颜色、纹理和光照等图形数据...

    效果超棒的Webgl模型-实木餐桌

    "效果超棒的Webgl模型-实木餐桌"标题表明我们讨论的是一个使用WebGL技术创建的实木餐桌的3D模型,它在网页上展示的效果非常出色。 在描述中虽然没有提供具体细节,但我们可以推测这个模型具有高度的逼真度,可能...

    效果超棒的Webgl模型-孙悟空

    这个“效果超棒的Webgl模型-孙悟空”显然是一款利用WebGL技术制作的、以中国古典名著《西游记》中的主角孙悟空为主题的三维模型。通过WebGL,开发者可以将复杂的3D模型和动画带到网页上,提供丰富的交互体验。 首先...

    效果超棒的Webgl模型-老式茶壶

    "效果超棒的Webgl模型-老式茶壶"这个项目,显然是一个展示高质量3D模型的实例,它利用WebGL技术将一个老式茶壶的三维模型呈现于网页之中。 首先,让我们深入了解WebGL的工作原理。WebGL基于OpenGL ES 2.0,这是一种...

    效果超棒的Webgl模型-老式照片机2

    "效果超棒的Webgl模型-老式照片机2"是一个利用WebGL技术制作的高质量3D模型,它呈现了一台复古的老式照片机,为网页添加了深度和真实感。 WebGL的基础是OpenGL ES 2.0,这是一种用于嵌入式设备的图形库,如智能手机...

    效果超棒的Webgl模型-两层小别墅2

    "效果超棒的WebGL模型-两层小别墅2"意味着我们正在讨论一个高质量的3D模型,它是一个两层小别墅的再现,通过WebGL技术在网页上展示。 首先,我们需要理解WebGL的基础。WebGL基于OpenGL ES 2.0,这是一项用于嵌入式...

    效果超棒的Webgl模型-两层公寓

    在这个名为“效果超棒的Webgl模型-两层公寓”的资源中,我们可能找到了一个精心设计的3D公寓模型,它利用WebGL技术在网页上展示了一个逼真的二层住宅空间。 WebGL的工作原理是通过JavaScript与GPU进行通信,绘制...

    效果超棒的Webgl模型-人体肺

    这个名为“效果超棒的Webgl模型-人体肺”的资源,显然是一个利用WebGL技术创建的、展示人体肺部结构的三维模型。在网页中,用户可以通过鼠标或触摸操作来旋转、缩放和平移模型,从而从不同角度观察肺部的细节。 ...

    效果超棒的Webgl模型-人体心脏跳动

    这个"效果超棒的Webgl模型-人体心脏跳动"项目,显然展示了一个交互式的、逼真的心脏跳动模拟,这涉及到多个IT领域的知识点。 首先,WebGL的基础是图形学。它使用顶点、纹理、着色器等元素来构建和渲染三维模型。在...

    效果超棒的Webgl模型-老式汽车

    这个名为“效果超棒的Webgl模型-老式汽车”的压缩包文件,显然包含了一个高质量的3D老式汽车模型,非常适合用于网页设计、游戏开发或者在线展示等场景。 首先,WebGL允许开发者直接在浏览器环境中创建复杂的3D场景...

    效果超棒的Webgl模型-巴士

    这个“效果超棒的Webgl模型-巴士”显然是一款使用WebGL技术创建的3D模型,它允许用户在网页上体验逼真的巴士模型。在网页设计和开发中,这种技术的应用极大地提升了用户体验,使得网站内容更加生动、直观。 首先,...

    效果超棒的Webgl模型-帆船

    在这个“效果超棒的Webgl模型-帆船”中,我们可以探讨WebGL在3D建模、渲染和交互性方面的应用。 首先,3D建模是创建三维物体的过程,包括帆船这样的复杂对象。这涉及到几何形状的构建、纹理的添加以及光照和阴影的...

    效果超棒的Webgl模型-机甲战士

    这个“效果超棒的Webgl模型-机甲战士”显然是一款使用WebGL技术创建的交互式3D模型,展示了机甲战士的形象。这种技术允许用户在网页上直接体验高质量的3D视觉效果,提供了丰富的互动性和沉浸感。 首先,我们要理解...

    效果超棒的Webgl模型-现代货船

    这个“效果超棒的Webgl模型-现代货船”压缩包很可能是包含了一艘现代货船的3D模型,设计者或开发者可以将其集成到网页中,展示逼真的海洋运输场景或进行互动式体验。 WebGL的核心在于它能够将复杂的3D几何数据、...

    效果超棒的Webgl模型-一堆石头

    这个“效果超棒的Webgl模型-一堆石头”很可能包含了一组精心设计的3D模型,这些模型可能用于创建虚拟现实场景、游戏或者网页中的装饰元素。现在,让我们深入探讨WebGL和3D建模的相关知识点。 首先,WebGL是Web图形...

    效果超棒的Webgl模型-驱逐舰

    "效果超棒的Webgl模型-驱逐舰"显然是一款利用WebGL技术创建的3D驱逐舰模型,它可能被应用于教育、游戏或者军事展示等领域,让用户在网页上就能欣赏到逼真的海上战舰。 WebGL的核心在于它可以访问硬件图形加速功能,...

    效果超棒的Webgl模型-尤达大师

    "效果超棒的Webgl模型-尤达大师"这个主题,显然涉及到的是利用WebGL技术创建的高质量3D模型,尤达大师是源自《星球大战》中的虚构角色,具有很高的辨识度,因此这个模型可能是粉丝或专业设计师为了展示WebGL技术潜力...

    效果超棒的Webgl模型-人体心脏

    这个“效果超棒的Webgl模型-人体心脏”是一个利用WebGL技术展示人体心脏结构的互动应用。它能够让用户在网页上直观地观察、旋转和交互操作心脏模型,提供了一种生动的学习和研究人体解剖的方式。 首先,我们要理解...

    效果超棒的Webgl模型-手表2

    为了实现"效果超棒",开发者可能还运用了高级的技术,比如PBR(物理渲染)来模拟真实世界中的光照和反射,或者使用LOD(细节层次)技术来优化性能,根据模型距离摄像机的远近动态调整细节级别。此外,实时阴影、环境...

    效果超棒的Webgl模型-老式战斗机

    这个“效果超棒的Webgl模型-老式战斗机”显然是一款使用WebGL技术实现的交互式3D模型,展示了老旧战斗机的精细细节和动态效果。 在WebGL中,模型通常由一系列几何形状(如点、线和多边形)组成,并通过纹理、光照和...

Global site tag (gtag.js) - Google Analytics