How to create a Captcha in zk ce version?

Creating an own Captcha component while it’s not in the zk community version.

As i work on the ‘forgotten password?’ module in openTruuls™ i would use a Captcha component for the user verification and i’m wondering that such a component is not in the zk community version. So openTruuls™ will be opensourced i need a Captcha component that developers can using without registering for a personal or commercial zk version.

After a few searching in the zk forum and the WWW i became a hint from Maik, the developer behind the jease cms ( www.jease.org ) to using the simpleCaptcha framework.

Argh, the biggest problem was to find a repository where a not corupted  version is downloading via the maven2 build system. And let me talk that i’m do it at last by a manual downloading in the linux shell on our web server because i don’t find a runing version.

Okay, after done this, the result is a little Captcha Controller who creates the Captcha which we can call in a static way. In the forgottenPassword Controller we use this Captcha and get the image from it which we assign to a zk image.

pieces of the zul-template

    .  .  .
								<!-- Captcha / Captcha -->
								<row>
									<space width="0" />
									<hbox>

										<image id="img_Captcha" />

										<toolbarbutton id="btnReCaptcha"
											image="/images/icons/sync_16x16.gif"
											tooltiptext="${c:l('common.ReCaptcha')}" />
									</hbox>
								</row>
   . . .


The complete dialog should looks like in this picture:

ForgottenPasswordController
ForgottenPasswordController

the FDCaptchaUtils.java


/**
 * EN: Utility class for creating a CAPTCHA.<br>
 * Captcha can be direct loaded into a org.zkoss.zul.Image<br>
 * DE: Hilfsklasse zur Erzeugung eines CAPTCHA.<br>
 * Captcha kann direkt in ein org.zkoss.zul.Image eingelesen werden.
 *
 * <pre>
 * Image img = new org.zkoss.zul.Image();
 * img.setContent(CaptchaUtils.getCaptcha().getImage());
 *
 * String verifyStr = captcha.getAnswer();
 * </pre>
 *
 * @author Stephan Gerth
 */
public class FDCaptchaUtils {

	public FDCaptchaUtils() {
	}

	/**
	 * Create a 5 digits captcha.
	 *
	 * @return
	 */
	public static Captcha getCaptcha() {

		Captcha captcha = new Captcha.Builder(170, 50).addText(new ColoredEdgesWordRenderer()).addNoise().addBackground(new GradiatedBackgroundProducer()).addBorder().build();

		return captcha;
	}

}


In the forgotten password controller we create the Captcha and insert it in the zk Image and handles the verify logic.

The needed methods in the controller code looks like this:

pieces of the ForgottenPassword controller

   . . .
   private Captcha captcha; // + getter/setter
   . . .

/**
 * Do a re-Captcha.<br>
 *
 * @param event
 */
private void doReCaptcha(Event event) {
	// init: disable the send password button
	btnReset.setDisabled(true);

	setCaptcha(FDCaptchaUtils.getCaptcha());
	img_Captcha.setContent(getCaptcha().getImage());
}

/**
 * 1. Checks if the email address is entered.<br>
 * 2. Verify the created captcha digits against the users input from a textbox.<br>
 * 3. Enable/disable the 'reset password' button.<br>
 *
 * @param event
 */
private void doVerifyCaptcha(Event event) {

     // init: disable the reset password button
     btnReset.setDisabled(true);

     // check if the tenant ID is entered
     if (StringUtils.isEmpty(longb_TenantID.getValue().toString().trim())) {
       	 throw new WrongValueException(longb_TenantID, Labels.getLabel("message.Error.CannotBeEmpty"));
     }

     // check if the email address is entered
	if (StringUtils.isEmpty(txtb_EmailAddress.getValue())) {
	    throw new WrongValueException(txtb_EmailAddress, Labels.getLabel("message.Error.CannotBeEmpty"));
	}

	// check if the captcha is verified correctly
	if (StringUtils.equals(txtb_VerifyCaptcha.getValue(), getCaptcha().getAnswer())) {
            btnReset.setDisabled(false);
	}
     }


Have fun with it.

Stephan Gerth

Dipl.rer.pol.


PS: Help to prevent the global warming by writing cool software

Leave a Reply

You must be logged in to post a comment.