Custom simple captcha in custom portlet for Liferay

Posted on by Charalampos Chrysikopoulos

In the last month we had to add different captchas in some liferay sites. Some customers were ok with the simple captcha, that comes per default with liferay and some others wanted to have the recaptcha of google, that also comes with liferay (not so default). And there was a third category of clients that weren't happy with a any of the above mentioned captchas and wanted a third solution.

In this post we will show how to add simple captcha in a form. To integrate simple catch in a form of a custom portlet is described in many articles like this one.

But there is not so many articles that describe how to make a captcha with a custom design and a refresh image button. So, here is a why way to implement it:

In the portlet class we need to change the code in two positions.

First in the serveResource method:

public void serveResource(ResourceRequest request, ResourceResponse response) throws PortletException, IOException {
  CaptchaUtil.serveImage(request, response);
}

The code above returns the image of the captcha.

And second in the action method:

public void processAction(ActionRequest actionRequest, ActionResponse actionResponse) throws IOException {
  try {
    CaptchaUtil.check(actionRequest);
  } catch (CaptchaTextException e) {
    SessionErrors.add(actionRequest, CaptchaTextException.class.getName());
  } catch (CaptchaMaxChallengesException e) {
    SessionErrors.add(actionRequest, CaptchaMaxChallengesException.class.getName());
  }
  ...
}

The code above checks the value of the captcha value and throws exceptions if the input is invalid.

Next, the jsp code. We need to write the html that shows the image, the refresh button and the text field. In addition, we need a javascript for the refresh button to replace the image with the new one.

Of course, our code is an example of how the html could be. Its is not a ready to use design.

First, the html:

  <%-- The url that returns the image --%>
  <portlet:resourceURL var="captchaURL"></portlet:resourceURL>
  <label><liferay-ui:message key="captcha-text" /></label>
  <div style="float:left;">
    <%-- the name of the field should be captchaText --%>
    <aui:input label="" name="captchaText" size="10" type="text" value="">
      <aui:validator name="required" />
    </aui:input>
  </div>
  <%-- the refresh button %-->
  <a href="#" class="refreshCaptcha captcha-reload" style="text-decoration: none;"></a>
  <%-- the image --%>
  <img style="float:left;padding:0px !important;margin-left:10px;" alt='<liferay-ui:message key="text-to-identify" />' class="captcha" border=0 src="<%= captchaURL + "&amp;" + new Random().nextInt(Integer.MAX_VALUE) %>" />

And the js code:

jQuery(".refreshCaptcha").click(function(evt){
  jQuery(".captcha").attr('src', '<%=captchaURL%>&amp;force='+encodeURIComponent(Math.floor(Math.random()*Math.pow(2, 53))));
  evt.preventDefault();
});
This entry was posted in Liferay and tagged captcha, Liferay, simplecaptcha by Charalampos Chrysikopoulos