Tuesday, October 9, 2007

SimpleCaptcha in Glassfish and Tomcat

I'm a big fan of SimpleCaptcha. It has ample configuration options and, after some tweaking, it looks good.

It's clean and easy for the user to read, but still accomplishes the purpose. I especially like that you can specify the characters to be used, thereby eliminating possibly confusing characters, such as 1 and l (that's the number one, and a lower case L).

I've used SimpleCaptcha in Fantasy Congress, running on Tomcat 5.5, and Glassfish v2. Although SimpleCaptcha is great, there were a couple quirks that I had to work around. By far the best thing about SimpleCaptcha is that the source is available, which I've needed both times to get it to work and which allows you to really change whatever you want.

1.) If you use SimpleCaptcha on a server running on some version of *nix without a GUI, you'll need to decapitate AWT. There are a lot of blogs describing how to set the system property java.awt.headless=true, but with limited success. I never got that to work and from the comments I've seen, I'm not alone. Another solution, as this blog describes, is to fake a GUI with the X window interface framebuffer server. I didn't see any reason to resort to that. My solution: I noticed that the problem was being caused in the renderWord(String word, int width, int height) method of nl.captcha.text.imp.DefaultWordRenderer at:

GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();

GraphicsDevice gd = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gd.getDefaultConfiguration();

The interesting part is that these objects are created, but never referenced, so I just commented them out and it worked fine. I later discovered an article on Java Boutique explaining why this was.

2.) I didn't like the line across the text that SimpleCaptcha generated by default. I know that it increases the effectiveness of a captcha but it simply wasn't necessary for my purposes. So I cracked open the source again and removed the line by commenting out these lines in nl.captcha.obscurity.imp.WaterRiple:

//draw line over the iamge and/or text
NoiseProducer noise = (NoiseProducer)Helper.ThingFactory.loadImpl(
Helper.ThingFactory.NOICEIMP, props);
noise.makeNoise(imageDistorted, .1f, .1f, .25f, .25f);
noise.makeNoise(imageDistorted, .1f, .25f, .5f, .9f);

Note: I set cap.obscurificator to nl.captcha.obscurity.imp.WaterRiple in the servlet declaration. If you're using a different class for obscurity, you'll need to modify the relevant class.

3.) Dropping the SimpleCaptcha setup I used in Tomcat into Glassfish resulted in a dump of nonsensical text to the display. I remedied this by editing nl.captcha.servlet.CaptchaServlet and changing the doGet method from:

String capText = captchaProducer.createText();
req.getSession().setAttribute(Constants.SIMPLE_CAPCHA_SESSION_KEY, capText);

String simpleC =(String) req.getSession().getAttribute(Constants.SIMPLE_CAPCHA_SESSION_KEY);

captchaProducer.createImage(resp.getOutputStream(), capText);


String capText = captchaProducer.createText();
req.getSession().setAttribute(Constants.SIMPLE_CAPCHA_SESSION_KEY, capText);

String simpleC =(String) req.getSession().getAttribute(Constants.SIMPLE_CAPCHA_SESSION_KEY);

captchaProducer.createImage(resp.getOutputStream(), capText);

It seemed logical that because the servlet is outputting an image (and in my case is mapped to /Captcha.jpg) that the content type should be an image, specifically "image/jpeg". Because adding the line resp.setContentType("image/jpeg"); solved the problem, I'm led to believe that the contentType was not being set before (though I haven't checked). However, that presents the interesting question of why SimpleCaptcha works in Tomcat without setting the contentType. I think this might have something to with the default mime types declared in the server-wide deployment descriptor in Tomcat. I'm not familiar enough with Glassfish yet to say whether it has an equivalent. I'd appreciate some insight if you have an explanation. For now, it works, and I don't have time to troubleshoot what works : )


Anonymous said...

Ralph Schuster compiled a bugfree version and offered for download here: http://techblog.ralph-schuster.eu/2007/11/21/simplecaptcha-for-serverssimplecaptcha-for-servers/.

Ryan said...

Thanks for the tip, though when I followed that link I got a 404 error...

I've actually made so many modifications to SimpleCaptcha by now that it's taken care of. In that regard, maybe I'll post my version someday. I'll have to document what I've changed first, so we'll see.

Anonymous said...

Oops, some Cut'n'Paste error. It's http://techblog.ralph-schuster.eu/2007/11/21/simplecaptcha-for-servers/

heikki said...

SimpleCaptcha is written to and compiled for Java 1.6. If you are looking for SimpleCaptcha to use with JDK 1.5, there is a distribution (both binary and source) at geonetwork.tv/captcha.

Printer ID Card said...

SimpleCaptcha has a simple configuration options. That's was great.

Printer Kartu | Printer ID Card | Cetak ID Card

xjd7410@gmail.com said...

insanity workout
louis vuitton outlet stores
adidas originals
michael kors outlet
coach factory outlet
replica watches
toms shoes
gucci handbags
louis vuitton handbags
coach outlet store online
timberland outlet
louis vuitton handbags
kate spade outlet
oakley sunglasses
oakley sunglasses
cheap jordans
oakley vault
burberry bags
air jordans
coach outlet store online clearances
beats solo 2
lebron james shoes
coach outlet store online
tory burch outlet
adidas ultra boost
cheap ray ban sunglasses
hollister shirts
ralph lauren polo
coach outlet store online clearances

mary Brown said...

Hi, Great.. Tutorial is just awesome..It is really helpful for a newbie like me.. I am a regular follower of your blog. Really very informative post you shared here. Kindly keep blogging. If anyone wants to become a Java developer learn from Java EE Online Training from India. or learn thru Java EE Online Training from India . Nowadays Java has tons of job opportunities on various vertical industry.