Spring in Practice

Willie Wheeler's Spring blog

How to reCAPTCHA Your Java Application

| Comments

reCAPTCHA is a novel CAPTCHA system developed by the School of Computer Science at my alma mater, Carnegie Mellon University. I won’t explain its coolness here since they do a good job of explaining that coolness themselves. What I will do here, though, is explain how to get your Java app reCAPTCHAed very quickly. Note however that reCAPTCHA is not tied specifically to Java.

In this tutorial I’m using Spring 2.5 MVC with annotations, and Commons Validator, but you’ll be able to follow this whether or not you’re using Spring and Validator.

These instructions are based on the instructions from the reCAPTCHA site, but I’m focusing specifically on Java integration whereas the site makes you dig around a bit to get the information. Not too bad, but enough that there’s value in my writing a Java-specific tutorial. :–)

Step 1. Get your account and key pair

First, go to the reCAPTCHA web site and create an account. As part of that account creation process you’ll have to specify the domain your reCAPTCHA will be protecting. The reCAPTCHA site will will give you a key pair for that domain. The key pair allows you to authenticate your reCAPTCHA requests to the reCAPTCHA servers, as we’ll see.

Step 2. Put the reCAPTCHA JavaScript in your app’s form

Here’s the JavaScript you need to put in your form, meaning in between the <form> and </form> tags. Put it wherever you would have normally put a CAPTCHA text box. This JavaScript will generate the reCAPTCHA box when users request the page:

<script type=“text/javascript”


</script> <noscript>

&lt;iframe src="http://api.recaptcha.net/noscript?k=&lt;your_public_key&gt;"
    height="300" width="500" frameborder="0"&gt;&lt;/iframe&gt;&lt;br&gt;
&lt;textarea name="recaptcha_challenge_field" rows="3" cols="40"&gt;
&lt;input type="hidden" name="recaptcha_response_field" 


It probably goes without saying, but I’ll say it anyway: you need to replace the two instances of <your_public_key> with the public key that you received during the account creation process. Be careful that you don’t use your private key by mistake. If you do that then everybody will be able to see your private key and act like they’re you.

Step 3. Run your app and make sure the reCAPTCHA is showing up

You should see it there in your form. It’s OK if you are coming from localhost or instead of the domain that you specified in the account creation step; reCAPTCHA will allow that. You should be able to click the buttons on the reCAPTCHA box and they should work.

After you goof around with that a bit, you’ll need to update your app itself so that it actually uses the reCAPTCHA box to validate the form submission.

Let’s turn now to the Java piece, where we validate the form and reCAPTCHA.

Step 4: Validate the form, including the reCAPTCHA

You’ll find it convenient to download the recaptcha4j library. It provides a simple API for submitting user responses to the reCAPTCHA server and finding out whether a user’s response is valid.

At this point I’m just going to lay some code on you. As mentioned above I’m using Spring 2.5 MVC with annotations and Commons Validator, but the main thing is for you to look at how I’m using the ReCaptchaImpl class and just copy that.

import net.tanesha.recaptcha.ReCaptchaImpl;
import net.tanesha.recaptcha.ReCaptchaResponse;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.Validator;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

@RequestMapping(value = “/comments/postcomment.do”, method = RequestMethod.POST) public String doPost(

    HttpServletRequest req,
    @RequestParam("articleId") long articleId,
    @RequestParam("recaptcha_challenge_field") String challenge,
    @RequestParam("recaptcha_response_field") String response,
    @ModelAttribute("comment") Comment comment,
    BindingResult result) {

// Validate the form (other than the reCAPTCHA)
validator.validate(comment, result);

// Validate the reCAPTCHA
String remoteAddr = req.getRemoteAddr();
ReCaptchaImpl reCaptcha = new ReCaptchaImpl();

// Probably don't want to hardcode your private key here but
// just to get it working is OK...

ReCaptchaResponse reCaptchaResponse =
    reCaptcha.checkAnswer(remoteAddr, challenge, response);

if (!reCaptchaResponse.isValid()) {
    FieldError fieldError = new FieldError(
        new String[] { "errors.badCaptcha" },
        "Please try again.");

// If there are errors, then validation fails.
if (result.hasErrors()) {
    String path = comment.getPagePath();
    log.debug("Form validation error; forwarding to " + path);
    return "forward:" + path;

// Else validation succeeds.
log.debug("Form validation passed");
comment.setDate(new Date());

// Post the comment
log.debug("Posting the comment");
articleService.postComment(articleId, comment);
log.debug("Comment posted");

return "redirect:" + comment.getPagePath() + "#comments";


Here’s the API for FieldError since I know that’s not clear from the code. Basically I’m using that to indicate that a validation error occurred and set up an error message for the user. If you’re not using Spring/Validator then you’ll do something else here.

The Comment class is just a class from my app, so don’t worry about that one.

You did it

Good job. If you’re feeling ambitious, try to defeat reCAPTCHA with super-advanced OCR. If you succeed then it represents an advance in OCR technology. Tell somebody and become famous. :–)

Post migrated from my Wheeler Software site.