Wednesday 25 April 2012

Implement Captcha in Liferay Portlet

Sometimes it is required to add captcha functionality into portlet. Liferay already have everything required, and already used captcha in some internal portlets (login, message board), but, it is implemented using with CaptchaPortletAction - what is not available for plugins (in case you are developing in plugin environment).
So, here is small receipt how to enable liferay's captcha in your portlet developed in plugin environment.

Generate Captcha

In portlet, in my case inherited from JSPPortlet (renamted to MVCPortlet in post-5.2.3) class we need to add method serverResource - something like this:
public class CaptchaSamplePortlet extends JSPPortlet {
    /** Serve Resource used for getting captcha
     *
     */
    @Override
    public void serveResource(ResourceRequest resourceRequest,
                             ResourceResponse resourceResponse) throws IOException, PortletException {
        try {
            com.liferay.portal.kernel.captcha.CaptchaUtil.serveImage(resourceRequest, resourceResponse);
        } catch (Exception e) {
            log.error(e);
        }
    }
}
This method doing everything - generated captcha and returned it's content (with all required http-readers into response), as well as placed required data into session

Display Captcha

Now, to place captcha into jsp you need to place:
<portlet:resourceURL var="captchaURL"/>
<liferay-ui:captcha url="<%= captchaURL %>"/>
That will place captcha control and point it to our portlet resourceURL to generate image
Now, you will have captcha and field to enter captcha text on your form generated by these tags.

Validate Captcha

To check captcha add followed function in your action-handler in portlet-class:
private void checkCaptcha(PortletRequest request) throws Exception {
        String enteredCaptchaText = ParamUtil.getString(request, "captchaText");

        PortletSession session = request.getPortletSession();
        String captchaText = getCaptchaValueFromSession(session);
        if (Validator.isNull(captchaText)) {
            throw new Exception("Internal Error! Captcha text not found in session");
        }
        if (!StringUtils.equals(captchaText, enteredCaptchaText)) {
            throw new Exception("Invalid captcha text. Please reenter.");
        }
    }

    private String getCaptchaValueFromSession(PortletSession session) {
        Enumeration<String> atNames = session.getAttributeNames();
        while (atNames.hasMoreElements()) {
            String name = atNames.nextElement();
            if (name.contains("CAPTCHA_TEXT")) {
                return (String) session.getAttribute(name);
            }
        }
        return null;
    }
What is all - now, you can do everything - display captcha, enter value - and check it


Contributed by : www.emforge.net

2 comments:

  1. Hi please help My portal request is not containing CAPTCHA_TEXT.

    ReplyDelete
  2. hi
    In my deployment atNames doesn't contain CAPTCHA_TEXT. What to do ???

    ReplyDelete