Knowledge base‎ > ‎

Captcha in Wicket with cache control and URL encryption

posted Apr 20, 2010, 5:06 AM by Szabolcs Szádeczky-Kardoss   [ updated Apr 22, 2010, 2:17 AM by István Soós ]
Wicket provides a lot of useful feature, among the others: it provides a lot out-of-the-box components. And if it doesn't suites you, you can easily create your own. Recently we have encountered this with a captcha component: we required a few different features (e.g. easier to read captcha), so we have created our own captcha panel.
  
We have choosen SimpleCaptcha as the image provider: it can create really difficult captchas, however it does suite our requirement for easier ones too, it can be configured like charm. Everything seemed to be easy and it basically worked for simple examples. However we have created an ajax tabbed panel that, on a few tab, contained this captcha. The problem hit us when the user switched between these tabs: the captcha text changed on the server side (expected) but the image hadn't on the client side (if you are entering the text, it will update, but that is not very user-friendly, is it?). What can you do in similar scenario?
  1. Set the cache control directives in the response header of the image
  2. Add a bit randomness to the image URL
  3. Obfuscate the URL of the image
Some believe that the first point is enough for most of the scenarios, some would go with the second option as well, however it is always a good idea to implement the third one too - it comes almost free and effortless with Wicket.

1. Set the cache control directives

You can set these as part of the DynamicWebResource or its subclass, e.g. the image resource we have used:
       BufferedDynamicImageResource bdir = new BufferedDynamicImageResource() {

private static final long serialVersionUID = 1L;

@Override
protected void setHeaders(WebResponse response) {
super.setHeaders(response);
response.setHeader("Cache-Control", "no-cache, must-revalidate, max-age=0, no-store");
}
};

2. Add a bit randomness to the image URL

Wicket dynamic image generates the URL for itself, but with a simple behavior you can modify it and add an extra item to the end of it:
       Image image = new Image("captchaImage", bdir);
image.add(new AbstractBehavior() {

private static final long serialVersionUID = 1L;

@Override
public void onComponentTag(Component component, ComponentTag tag) {
tag.getAttributes().put("src",
tag.getAttributes().getString("src") + "&nanoTime=" + System.nanoTime());
}

});
add(image);

3. Obfuscate the Wicket URLs

This method will obfuscate every non-bookmarkable URL in your application. This is not only for the captcha images, but it helps you to expose most of your internals, and prevents search engines to index them as part of the URL. This guide can help you to achieve more, but basically you need to add these lines in your Application class:
   @Override
protected IRequestCycleProcessor newRequestCycleProcessor() {
return new WebRequestCycleProcessor() {
@Override
protected IRequestCodingStrategy newRequestCodingStrategy() {
return new CryptedUrlWebRequestCodingStrategy(new WebRequestCodingStrategy());
}
};
}

published: 2009-07-22, a:István, y:2009, l:captcha, l:encryption, l:wicket
Comments