Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 16

1.

Dashboard
2. JCaptcha
3. …
4. How to
5. 5 minutes application integration tutorial
View a printable version of the current page.

Home  Log In

FAQ JCaptcha

5 minutes application integration tutorial


One
minute set up
(Since 2.0)
Added by marc antoine garrigue, last edited by Antoine Véret on Sep 03, 2009
5 minutes
(view change)
application
integration tutorial Labels:
Spring This page demonstrates how to use jcaptcha in your application.
configuration
Image This tutorial uses the CaptchaService and sub components (see Architecture
Components overview).
Reference
Customiz
e an engine

JCaptcha
Install it
Maven Site
Issue
Tracking Maven2 users
Login Add the following dependency to your project POM
Sign Up
<dependency>
<groupId>com.octo.captcha</groupId>
Page Operations
<artifactId>jcaptcha</artifactId>
Browse Space <version>1.0</version>
</dependency>

Without Maven2
Add jcaptcha-all.jar (provided in bin-distribution) and commons-collection-3.2 or
greater (not provided see commons collection ) to your application class path, ie
in you WEB-INF/lib folder.

Implement a CaptchaService
It must be a singleton

import com.octo.captcha.service.image.ImageCaptchaService;
import
com.octo.captcha.service.image.DefaultManageableImageCaptc
haService;

public class CaptchaServiceSingleton {

private static ImageCaptchaService instance = new


DefaultManageableImageCaptchaService();

public static ImageCaptchaService getInstance(){


return instance;
}
}

Code an image captcha servlet


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

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 java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class ImageCaptchaServlet extends HttpServlet {

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().getImageChallengeFor
ID(captchaId,

httpServletRequest.getLocale());

// a jpeg encoder
JPEGImageEncoder jpegEncoder =

JPEGCodec.createJPEGEncoder(jpegOutputStream);
jpegEncoder.encode(challenge);
} catch (IllegalArgumentException e) {

httpServletResponse.sendError(HttpServletResponse.SC_NOT_F
OUND);
return;
} catch (CaptchaServiceException e) {

httpServletResponse.sendError(HttpServletResponse.SC_INTER
NAL_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();
}
}

Add it to your web.xml


<servlet>
<servlet-name>jcaptcha</servlet-name>
<servlet-class>ImageCaptchaServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>

And
<servlet-mapping>
<servlet-name>jcaptcha</servlet-name>
<url-pattern>/jcaptcha</url-pattern>
</servlet-mapping>

The form
Provide a form containing the captcha challenge (the image) and an input text for
the response

<img src="/jcaptcha">
<input type='text' name='j_captcha_response' value=''>

the validation routine


Handle the post (using a servlet, or whatever).
The validateCaptchaForId method will return true if the response is correct.

Boolean isResponseCorrect =Boolean.FALSE;


//remenber that we need an id to validate!
String captchaId =
httpServletRequest.getSession().getId();
//retrieve the response
String response =
httpServletRequest.getParameter("j_captcha_response");
// Call the Service method
try {
isResponseCorrect =
CaptchaServiceSingleton.getInstance().validateResponseForI
D(captchaId,
response);
} catch (CaptchaServiceException e) {
//should not happen, may be thrown if the
id is not valid
}

//do something according to the result!

Want some more


Try customization and more integration
Have a look to the modules provided to see how to integrate it with other frameworks :
Change the Captcha generation configuration
Use JCaptcha with a Spring configuration

Contribute !
Please put some code showing integration with a new framework in a child page of the
Comments  (Hide Comments)
hehe, you might want to add a captcha here! 

 Posted by Anonymous at Sep 27, 2005 10:25

Thank you, great way to start! / Frans Lundberg

 Posted by Anonymous at Oct 29, 2005 16:15

Calling

CaptchaServiceSingleton.getInstance().validateResponseForID(captchaId,
captcha_response);

twice gives me

com.octo.captcha.service.CaptchaServiceException: Invalid ID, could not validate

I am trying to check the response via an ajax service, so may call this a few
times.

First time, after the captcha is created, it is fine.


Called again it gives me the above exception.

Is this supposed to happen, that you can only validate once?

Is there a good way to find out what the word should be, so that I don't have to
run validate?

 Posted by Dino Fancellu at Apr 05, 2006 13:39

Hi,

I'm trying to create a JSP page to display "the form" section listed above. I have
several questions:

1: Could you write the code into the tutorial for how to instantiate the
CaptchaService on that page? Do I need to create a reference to a bean on that
page? If so, please show me how exactly to write all of the code for that page to
work.

2: how does writing "jcaptcha" for the "img src" in <img src="jcaptcha"> create
an image? I feel like there should be some reference to the CaptchaService to be
able to correctly display an image from the service? Should something else be
written there for me to get it to work?

3: when you say "Handle the post (using a servlet, or whatever)" does that mean
we can just post the form to another JSP page with the validation routine? I'm
not clear what you are referring to.

Thank you for your help!

 Posted by Courtenay at Jul 26, 2006 18:19

Hooha!!
It works for me

Very well guided


Thanks !!

 Posted by Vinod Kumar Kashyap at Oct 20, 2006 09:18

The implementation described above worked fine for me but I want to use a
different type of image (one that is easier to understand the letters). I
implemented the CaptchaServiceSingleton as follows:

private static ImageCaptchaService instance = initializeService();

private static ImageCaptchaService initializeService()


{
SimpleListImageCaptchaEngine engine = new SimpleListImageCaptchaEngine();
engine.addFactory(new GimpyFactory(new
RandomWordGenerator("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), new
ComposedWordToImage(new RandomFontGenerator(new Integer(12), new
Integer(16)), new FunkyBackgroundGenerator(new Integer(200), new
Integer(100)), new RandomTextPaster(new Integer(6), new Integer(10),
Color.BLACK))));
return new DefaultManageableImageCaptchaService(new
FastHashMapCaptchaStore(), engine, 180, 100000, 75000);
}

I then create the image as described except using only the user's session id. The
image is created as expected but when I call validateResponseForID, no matter
what the response is (even an empty string), it always returns true. Did I do
something wrong? What could be causing it to work improperly?

 Posted by Nathan Oertel at Feb 21, 2007 07:15

Hello Nathan. I have done the same thing and am experiencing the same
problems. Did you ever find a solution to this?

 Posted by Martin Thorpe at Jul 18, 2007 09:49

I implemented a modified version of the CaptchaServiceSingleton to change the


default image size and background color:

public static ImageCaptchaService getInstance()


{
    ListImageCaptchaEngine engine = new SimpleListImageCaptchaEngine();
    /* I instantiate here a FontGenerator, BackgroundGenerator, TextPaster and
WordGenerator */
    ComposedWordToImage composedWordToImage = new
ComposedWordToImage(fontGenerator, backgroundGenerator, textPaster);
    engine.addFactory(new GimpyFactory(wordGenerator,
composedWordToImage));
    return new DefaultManageableImageCaptchaService(new
FastHashMapCaptchaStore(), engine, MIN_STORAGE_DELAY, MAX_STORE_SIZE,
LOAD_BEFORE_GARBAGE_COLLECTION);
}

My problem is that when I load the page, I sometimes get the desired image size
and background and sometimes not (in this case, I get the funky 3 color gradient
background)... I guess it is because the engine is initialized with a default captcha
factory? For this reason, I tried to do the following to reset the engine factories:

ImageCaptchaFactory[] captchaFactories =

Unknown macro: {new GimpyFactory(wordGenerator, composedWordToImage)}

;
engine.setFactories(captchaFactories);

After that, nothing works anymmore... Any idea on what I should do?

 Posted by Jimmy at May 01, 2007 10:00

Greetings, Jimmy.

SimpleListImageCaptchaEngine class is already has own factories. If you want do


define custom CaptchaEngine I suggest to create your engine implementation and
override buildInitialFactories() method in it.

For example:

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(7), new Integer(7), cgen,
true);

BackgroundGenerator backgroundGenerator = new


FunkyBackgroundGenerator(new Integer(200), new
Integer(100));

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(20), new Integer(35),
fontsList);

WordToImage wordToImage = new


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

If so, your CaptchaServiceSingleton should be like the following:

public class CaptchaServiceSingleton {


private static ImageCaptchaService instance;
static {
instance = new
DefaultManageableImageCaptchaService(
new FastHashMapCaptchaStore(),
new MyImageCaptchaEngine(),
180,
100000,
75000);
}
public static ImageCaptchaService getInstance(){
return instance;
}
}

Regards, Dmitry Kudrenko (ARDAS group)

 Posted by Dmitry Kudrenko at Jun 27, 2007 09:05

This was a great post; thank you! I was able to get it working in my application
perfectly. I adjusted the image size and the number of characters to meet my
specific requirements. I just have one question: the text is being pasted in on the
background, right on the left edge. Is there a way to center the text, or at least
to have a left margin?

 Posted by Kevin Ilsen at May 30, 2009 17:00

I can confirm the bug reported by Jimmy.

Here is the exception:


java.lang.ExceptionInInitializerError
at net.bacman.utils.ImageCaptchaServlet.doGet(ImageCaptchaServlet.java:42)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:115)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:92)
at
com.caucho.server.dispatch.ServletFilterChain.doFilter(ServletFilterChain.java:10
6)
at com.caucho.server.cache.CacheFilterChain.doFilter(CacheFilterChain.java:209)
at
com.caucho.server.webapp.WebAppFilterChain.doFilter(WebAppFilterChain.java:1
73)
at
com.caucho.server.dispatch.ServletInvocation.service(ServletInvocation.java:229
)
at
com.caucho.server.hmux.HmuxRequest.handleRequest(HmuxRequest.java:420)
at com.caucho.server.port.TcpConnection.run(TcpConnection.java:511)
at com.caucho.util.ThreadPool.runTasks(ThreadPool.java:520)
at com.caucho.util.ThreadPool.run(ThreadPool.java:442)
at java.lang.Thread.run(Thread.java:619)
Caused by: com.octo.captcha.engine.CaptchaEngineException: This factory is not
an image captcha factory class com.octo.captcha.image.gimpy.GimpyFactory
at
com.octo.captcha.engine.image.ListImageCaptchaEngine.setFactories(ListImageC
aptchaEngine.java:95)
at
net.bacman.utils.CaptchaServiceSingleton.<clinit>(CaptchaServiceSingleton.java:
39)
... 12 more

The setFactories method:

/**
* @param factories new captcha factories for this
engine
*/
public void setFactories(CaptchaFactory[] factories)
throws CaptchaEngineException {
if (factories == null || factories.length == 0) {
throw new CaptchaEngineException("impossible
to set null or empty factories");
}
ArrayList tempFactories = new ArrayList();

for (int i = 0; i < factories.length; i++) {


if
(ImageCaptchaFactory.class.isAssignableFrom(factories[i].g
etClass())) {
throw new CaptchaEngineException("This
factory is not an image captcha factory " +
factories[i].getClass());
}
tempFactories.add(factories[i]);
}

this.factories = tempFactories;
}

I thought perhaps I should use the CustomFactoriesImageCaptchaEngine.java,


but that class isn't in the build.   Any thoughts on how this should be fixed?

Thanks,
Michael 

 Posted by Michael Bacarella at May 26, 2007 17:52

I have implemented 5 minutes application integration using jcaptcha-all-1.0-


RC6.jar. It works but sometimes, I am getting weird images (which are not
letters or numbers or not even a type able symbol from keyboard).
httpServletRequest.getLocale() also returns en_US. Can anybody help me how to
get rid of these weird images? The image is seen as follows

I also failed to implement the customize images using this example. How to get
the customize images or background other than default one. Thanks

 Posted by Rafiqul Islam at May 30, 2007 15:40

Hi Marc

Great article.

You stated that the CaptchaService must be instantiated as a singleton.

Will this have any issue in a clustered environment?

Regards

 Posted by Eric Tan at Oct 05, 2007 05:19

Hi Eric, please look at this page : Clustering with JBossCache CaptchaStore

 Posted by Antoine Véret at Apr 04, 2008 15:41

The codec used for JPEG generation will be deprecated in futere releases of JDK.
It should be changed with the following lines:

import javax.imageio.ImageIO;
........

public class ImageCaptchaServlet extends HttpServlet {

   protected void doPost(HttpServletRequest request, HttpServletResponse


response)
   throws ServletException, IOException {

        response.setHeader("Cache-Control", "no-store");
        response.setHeader("Pragma", "no-cache");
        response.setDateHeader("Expires", 0);
       
        response.setContentType("image/png");       
       
        //the same id must be used to validate the response,
        //the session id is a good candidate!
        String captchaId = request.getSession().getId();
        // call the ImageCaptchaService getChallenge method
        BufferedImage image =
               
CaptchaServiceSingleton.getInstance().getImageChallengeForID(captchaId,
                request.getLocale());       
       
       
        ServletOutputStream os = response.getOutputStream();
        //Writing the image to outputstream
        ImageIO.write(image, "png", os);
        // flush it in the response
        os.flush();
        os.close();
   }
......
}

 Posted by Sergio Gtz at Nov 06, 2007 18:59

Please help i need documentation or a tutorial for integrating the sound captcha
functionallity i cannot find anything, it would be nice to have a tutorial like the 5
min app integration using sound captcha.

thanks.

 Posted by rm at Mar 18, 2008 22:16

Hi,
I am looking for JCaptcha with sound integration.

It seems JCaptcha is supporting sound. But I don't know how to integrate sound
with JCaptcha.
Anyone please send the steps to integrate JCaptcha with sound.

Adv. thanks,

 Posted by Fra at Oct 17, 2008 15:49

Hi Eric,

I thought about the same. But if you configure your load balancer to have sticky
sessions, then it's no problem, because the second request containing the
response on the challenge will land in the same application server, hence in the
same JVM. The only problem with this is in the rare case when the first request is
sent to server A, then it crashes, then the second request goes to server B - it
will fail then, of course. But then the user repeats the submit with a different
challenge coming from server B, and it will (hopefully) succeed.

 Posted by Gergely Szakács at Mar 28, 2008 11:50

JCaptcha Integration with Tapestry

This is for Apache Tapestry users, we can integrate JCaptcha in Tapestry


application easily as it supports StreamResponses, Therefore don't need any
Servlet to be maintained.

First create a tapestry service for JCaptcha

public interface MyCaptchaService {


    public boolean isValidUserResponse(String
verificationCode, String captchaId);
    public StreamResponse generateImageChallenge(String
captchaId);
}

Implementation class

public class MyCaptchaServiceImpl implements


MyCaptchaService {
   
    private final ImageCaptchaService serviceInstance;  
   
    public MyCaptchaServiceImpl(ImageCaptchaService
serviceInstance {
        this.serviceInstance = serviceInstance;         
    }
   
    public StreamResponse generateImageChallenge(String
captchaId) {
       
        BufferedImage imageChallenge =
serviceInstance.getImageChallengeForID(captchaId,
Locale.US);
        ByteArrayOutputStream os = new
ByteArrayOutputStream();
     
        try {           
            ImageIO.write(imageChallenge, "PNG",
os);           
            final InputStream is = new
ByteArrayInputStream(os.toByteArray());
            return new StreamResponse() {
                public String getContentType()  { return
"image/png"; }
                public   InputStream getStream() throws
IOException { return is; }
                public void prepareResponse(Response
response) {
                    response.setHeader("Pragma", "no-
cache");
                    response.setHeader("Cache-Control",
"no-cache");
                    response.setDateHeader("Expires",0);
                }
            };
        }
        catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public boolean isValidUserResponse(String


verificationCode, String captchaId) {
       
        if
(Boolean.parseBoolean(properties.value("captcha.validate.s
kip")))
            return true;
     
        try {
            return
serviceInstance.validateResponseForID(captchaId,
verificationCode);
        } catch (CaptchaServiceException e) {
            throw new RuntimeException(e);
        }
    }
   
    public class ImageCaptchaImpl extends ImageCaptcha{
        public static final long serialVersionUID = 1;
        public ImageCaptchaImpl(String question,
BufferedImage challenge) {
            super(question,challenge);
           
        }
        public Boolean validateResponse(Object obj){
            return Boolean.FALSE;
        }
       
    }
}

 Add a build method for this service in your AppModule.java

public MyCaptchaService buildCaptchaService() {


        return new MyCaptchaServiceImpl(new
DefaultManageableImageCaptchaService());
    }

 The page where you use ex: MyPage.tml

<img
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.
xsd" src="${imageURL}"  align="absmiddle" alt="Dynamic
Verification Code" /> 

 in MyPage.java

public class MyPage {

    @Inject private ComponentResources resources;


    @Inject private CaptchaService captchaService;
    @Inject private RequestGlobals requestGlobals;
         

    public Link getImageURL() {


        return resources.createActionLink("image", false);
    }
    //executes when image is rendered
    public Object onImage() {    
        return
captchaService.generateImageChallenge(requestGlobals.getHT
TPServletRequest().getSession().getId());
    }
}
 

          when you want to verify

          

@Inject             private
MyCaptchaService      captchaService;
           @Inject             private RequestGlobals     
requestGlobals; 
            String sessionId =
requestGlobals.getHTTPServletRequest().getSession().getId(
);
            if (!
captchaService.isValidUserResponse(verificationCode,
sessionId)) {
                form.recordError("Verification code you
entered does not match");
            }

 I would like to thanks Mr. Dmitry Kudrenko who has posted about extending of
Captcha engine.

Best Regards
Lakshitha Ranasinghe,
Colombo, Sri Lanka. 

 Posted by Lakshitha Ranasinge at May 07, 2008 09:37

Hi Lakshitha Ranasinghe,

Can you write addition a tutorial for JCaptcha Integration with Tapestry 4 ? At
present, between Tapestry 4 and Tapestry 5 have very large difference. For
instance, Tapestry 4 doesn't support the StreamResponse interface and other
cleasses/service.

please help me to take an artical about JCaptcha Integration with Tapestry 4.

Thank you very much,

Bao

 Posted by Luu Kim Bao at Jun 12, 2008 12:11

It worked when I used (JSP + servlet) but will it also work if I implement it on
(HTML + VelocityServlet) ?

 Posted by Bien Angelo Relucano at Sep 16, 2008 09:50

Hi guys,

I have integrated jcaptcha in my projcet it is working fine.But code in the servlet


using some of the sun proprietary api classes so i am getting this kind of warning
messages.Can any one tell me how to avoid these warnings.

These are the two lines using the proprietary api

JPEGImageEncoder jpegEncoder =
JPEGCodec.createJPEGEncoder(jpegOutputStream);
jpegEncoder.encode(challenge);

warning: com.sun.image.codec.jpeg.JPEGCodec is Sun proprietary API and may


be removed in a future release

warning: com.sun.image.codec.jpeg.JPEGImageEncoder is Sun proprietary API


and may be removed in a future release

Thankyou,
ravindra

 Posted by ravindra at Oct 27, 2008 06:57

Hi all,

I am able to generate captcha without any warning messages.But the captcha is


generating words containing only alphabets.I want to generate alpha nuemeric
captcha.Can anyone tell me how to generate
alpha numeric captcha.

Thankyou,
ravindra

 Posted by ravindra at Oct 27, 2008 08:23

a colleague and i have written an article about GWT, which includes a description
of how to integrate JCaptcha with GWT. The article and the free source code are
at:

http://www.maxant.co.uk/whitepapers.jsp

The paper is called "Enterprise GWT: Combining Google Web Toolkit, Spring and
Other Features to Build Enterprise Applications"

 Posted by Ant Kutschera at Feb 14, 2010 10:55

It's great!! Good job!! 


I am a Spanish novice programmer, and I would know how I can put a message
below the form, as right or wrong answer.
How could I?

 Posted by Andy Wandy at Oct 07, 2010 14:11

Hi All,

Please can anyone help me to integrate the sound captcha and image captcha in
the struts application.The requirment is letters which are generated in the image
captcha could be listened by sound captcha and also validate the response
submited by user.

Thanks in advance.

Thanks, Biswajit

 Posted by Biswajit Sahoo at Nov 16, 2010 16:06

Powered by a free Atlassian Confluence Open Source Project License granted to JCAPTCHA. Evaluate Confluence


today.

 Powered by Atlassian Confluence 3.1.2, the Enterprise Wiki.

 Bug/feature request –

 Atlassian News –

 
 Contact administrators

You might also like