Monday, March 29, 2010

Simple Captcha with Struts



In this post we will learn how to use simple Captcha with Struts to create Captcha for confirming that the interacting user is a person not a computer..

Here is a 5-steps implementation:

1.Download the Simple Captcha jar:

Here is the link:

http://sourceforge.net/projects/simplecaptcha/files/SimpleCaptcha/1.1.1/SimpleCaptcha-1.1.1.jar/download

2.Add the jar to your web project classpath:

Typically inside web-inf/lib folder

3.Add new servlet to your web project:
Name: CaptchaServlet

*Implement doGet method:

try {
Captcha captcha = new Captcha.Builder(200, 50).addText(new DefaultTextProducer(6)).gimp(new DropShadowGimpyRenderer()).build();
//200, 50 is the size, 6 is the number of letters to use, we choose the shadow renderer.
response.setHeader("Cache-Control", "no-store");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
// don't cache it , don't store it, expire after 0 second, so with refresh new image loaded
response.setContentType("image/jpeg");
//image type
CaptchaServletUtil.writeImage(response, captcha.getImage());
//write the image
request.getSession().setAttribute("CorrectAnswer",
captcha.getAnswer());
//store the answer for this in session
} catch (Exception e) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}

4.In Your action class: (where the html form that include Captcha is submitted) add the following code:

//registerFormBean is the form bean of the current action and captcha response is the field of user input

String answer =
request.getSession().getAttribute("CorrectAnswer");
if (answer == null || registerFormBean.getCaptchaResponse()==null || !answer.equals(registerFormBean.getCaptchaResponse())){
ActionErrors errors = new ActionErrors();
errors.add("error1", new ActionMessage("error.captcha"));
}

error.captcha contain the following value in resource bundle:
error.captcha=Invalid value of shown text!

//so we check either pass successfully or add to errors error regarding captcha.


5.In the JSP file , add the following:

<img id="captchaImg" src="/...context..../CaptchaServlet" alt="Captcha Image" height="45">
<img src="/...context..../images/reload.jpg" alt="Reload" onclick="document.forms[0].captchaImg.src='/...context..../CaptchaServlet?id='+Math.random();" style="cursor:pointer"/>
<br><font color=red>*</font>Enter Value Shown:
<br><html:errors property="error1"/><br>
<html:text property="captchaResponse" maxlength="6" style="width:100pt"/>

-This will construct the Captcha and the text field to enter the value and struts error message to show errors in captcha response, plus the refresh icon.



NOTE: a good trick we used here is the java script Math.random() function , this way prevent certain browsers like Firefox 3.0 to cache the URL and keep posting the same Captcha image , this enforce it to get the new value without doing any more effort.

Here is how it will looks like:

Invalid content Error Message shown here:



For more details refer to the web site :

http://simplecaptcha.sourceforge.net/index.html


20 comments:

  1. Thanks for posting! I needed help getting my captcha to reload and this worked very nicely.

    ReplyDelete
  2. Thanks a ton! I really a quick solution and ur post helped me :)

    ReplyDelete
  3. hi sir,
    this is really goood.
    sir, i facing a problem for few days . hope you can give an answer.

    how to conditionally populate drop down list.Like countries in one drop down list and when i select a country corresponding list og states is shown in other .

    i can do it using javascript but do not know i to do it using struts.

    if you might write a blog on same, it will be of great help.

    ReplyDelete
  4. Hi sir i implementes this simplecaptcha in my spring login application ,every thing works fine ,but i need to add refresh button i am not able to do it,but i saw your example but it is litte bit confusion.if you have source code please make it available for download. please help me ,

    ReplyDelete
    Replies
    1. Which part is confusing for you so i can put the code ?

      Delete
    2. In jsp file this part of refresh button

      img src="/...context..../images/reload.jpg" alt="Reload" onclick="document.forms[0].captchaImg.src='/...context..../CaptchaServlet?id='+Math.random();" style="cursor:pointer"

      Delete
    3. replace /...context.../images/reload.jpg with your image path and replace /..context../CaptchaServlet with your CapchaServlet path ..
      Context=Context Root of the application.

      Delete
  5. Actually i didn't write any own servlet i just added this in web.xml and simplecaptcha-1.1.1.jar to buildpath

    SimpleCaptcha
    com.manam.captcha.servlet.SimpleCaptchaServlet


    SimpleCaptcha
    /simpleCaptcha.jpg


    in login.jsp the below line under password field

    img id="captcha" src="" width="75"

    the above line is generating me the captcha image with text

    ReplyDelete
    Replies
    1. OK, please follow my blog post and create this wrapper servlet and use it instead..

      Delete
    2. sir i am confusing about your onclick functionality
      onclick="document.forms[0].captchaImg.src='/...context..../CaptchaServlet?id='+Math.random();" ,what is that code document.forms[0].captchaImg.src you wrote any script for that functionality.

      Delete
    3. Please read the post carefully and follow the steps!
      This refer to this image:
      <img id="captchaImg" src="/...context..../CaptchaServlet" alt="Captcha Image" height="45">

      Delete
  6. Its working for me i just added
    a href="#" title="Refresh Captcha" onclick="document.getElementById('captcha').src = 'simpleCaptcha.jpg?sid=' + Math.random(); return true"
    below default generating captcha.i really thank you so much for your valuable time and support .by talking with you i got this idea.once again thanks a lot

    ReplyDelete
  7. Hi Osama sir ,do you have any idea how to validate this captcha response value in spring security login .please help me i want to validate this response value while authenticating the login credentials,or other wise please post your full validation action class so that i can understand the logic there.please help me sir

    Thanks

    ReplyDelete
    Replies
    1. The correct answer is in the session: String answer = request.getSession().getAttribute("CorrectAnswer");

      & you need to compare it with the sent parameter in the request that correspond to the field name/backing bean..

      Delete
    2. sir then what about this registerFormBean.getCaptchaResponse(),did you initialize captcharesponse field with anything.please post the intialization of captcharesponse field.

      Delete
    3. It is amazing, you should know struts before asking, in Struts the html field get populated in this bean that is mapped to that JSP file.. so i am getting the value directly from it, you need to get it same way as you do in spring.

      Delete
    4. oh sorry i thought you wrote that class for only validation
      of captcha response.little confusion in my thinking.

      Delete
  8. I Created my servlet CustomCaptcha.java and added doGet(), as mentioned. I included this in my web.xml too. Lastly, in my JSP, i'm using image source = customCaptcha.png,but no image gets displayed on JSP.

    Am i missing out on anything?

    ReplyDelete
    Replies
    1. You must put the context root before custom captch in img src=.... as described in the post.

      Delete