您的位置:首页 > 其它

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

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

可能是我太过时了!)

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

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

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

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

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



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

这里我发上我的源代码:

web.xml中:

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类:

Java代码


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

Java代码


<%@ 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: (用来验证的页面 )

Java代码


<%@ 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 ,非常感谢白衣的共享,让我们这样的菜鸟学到很多东西.)



其中代码如下:

Java代码


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类修改一下:

Java代码


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类:

改动如下:

Java代码


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, 先写到这,希望对有需要的人有帮助。

如果有人懒得敲代码,我这里附上我的工程源代码, 不过我还是觉得,咱弄技术的人, 就得把键盘当筷子, 你见过非常饿,但不想拿筷子的人吗?(别说老外用叉子……)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: