Follow by Email

Friday, 2 January 2015

Using captcha with ADF Faces (Integrate Kaptcha project with Oracle ADF)

First of all wishing a very Happy New Year to all of you, learn more n more ADF this year :)


This post is about using captcha challenge in ADF Faces, captcha is used to determine whether user is a human or not
CAPTCHA stands for-Completely Automated Public Turing test to tell Computers and Humans Apart
Frank Nimphius posted about 'captcha with ADF Faces' using "Simple Captcha" project.
You can read complete article- http://www.oracle.com/technetwork/developer-tools/jdev/captcha-099103.html



For this post I am using modern version of simplecaptcha project called Kaptcha, project provides a servlet that is responsible for generating captcha image and there are various configuration parameters to change look n feel of captcha image
See project documentation - https://code.google.com/p/kaptcha/
Download jar file- https://code.google.com/p/kaptcha/downloads/list

Now see the steps to integrate Kaptcha project with Oracle ADF
  • Create a FusionWeb Application, attach kaptcha-2.3.2 jar to viewController project, also see How to use "Kaptcha"-https://code.google.com/p/kaptcha/wiki/HowToUse


  • Next step is to add kaptcha servlet reference in web.xml file

  •  <servlet>
            <servlet-name>Kaptcha</servlet-name>
            <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>Kaptcha</servlet-name>
            <url-pattern>/kaptchaimage</url-pattern>
        </servlet-mapping>
    

  • Add an af:image on page to show captcha, image source is referenced from servlet mapping

  • <af:image id="i1" partialtriggers="l1" shortdesc="Captcha" source="/kaptchaimage">
    

  • Default configuration for captcha image is completed , I have added an af:inputText and button on page to enter captcha result .

  • <af:panelBox text="Captcha Demo- www.awasthiashish.com" id="pb1" showDisclosure="false"
                                     inlineStyle="width:350px;">
                            <f:facet name="toolbar"/>
                            <af:spacer width="0" height="10" id="s3"/>
                            <af:panelFormLayout id="pfl1">
                                <af:panelGroupLayout id="pgl1" layout="horizontal">
                                    <af:image source="/kaptchaimage" id="i1" partialTriggers="l1" shortDesc="Captcha"/>
                                    <af:spacer width="10" height="0" id="s4"/>
                                    <af:link id="l1" icon="#{resource['images:reload.png']}" shortDesc="Refresh Captcha"/>
                                </af:panelGroupLayout>
                                <af:inputText label="Enter text" id="it1" binding="#{ReadCaptchaBean.entrdCaptchaBind}"
                                              contentStyle="font-weight:bold;"/>
                                <af:button text="Submit" id="b1" actionListener="#{ReadCaptchaBean.readCaptchAction}"/>
                            </af:panelFormLayout>
                        </af:panelBox>
    

  • Run application and see how captcha image is appearing on page


  • It looks good :-), now see the managed bean code written in submit button's action. This code checks actual captcha value with entered value

  •     //Binding of inputText to get entered value
        private RichInputText entrdCaptchaBind;
    
        public void setEntrdCaptchaBind(RichInputText entrdCaptchaBind) {
            this.entrdCaptchaBind = entrdCaptchaBind;
        }
    
        public RichInputText getEntrdCaptchaBind() {
            return entrdCaptchaBind;
        }
        
        /**Method to check whether entered value is correct or not
         * @param actionEvent
         */
        public void readCaptchaAction(ActionEvent actionEvent) {
            FacesContext fctx = FacesContext.getCurrentInstance();
            ExternalContext ectx = fctx.getExternalContext();
            HttpServletRequest request = (HttpServletRequest) ectx.getRequest();
            //KAPTCHA_SESSION_KEY- The value for the kaptcha is generated and is put into the HttpSession. This is the key value for that item in the session.
            String kaptchaExpected =
                (String) request.getSession().getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
            //Get entered value of captcha using inputText binding
            String kaptchaReceived = entrdCaptchaBind.getValue().toString();
            System.out.println("Entered Value-" + kaptchaReceived + " Expected Value-" + kaptchaExpected);
            if (kaptchaReceived == null || !kaptchaReceived.equalsIgnoreCase(kaptchaExpected)) {
                FacesMessage errMsg = new FacesMessage("Invalid Value");
                errMsg.setDetail("Incorrect captcha value- Not Human");
                errMsg.setSeverity(FacesMessage.SEVERITY_ERROR);
                fctx.addMessage(entrdCaptchaBind.getClientId(), errMsg);
            } else {
                FacesMessage errMsg = new FacesMessage("Correct Value");
                errMsg.setDetail("Hello this is the right guess");
                errMsg.setSeverity(FacesMessage.SEVERITY_INFO);
                fctx.addMessage(entrdCaptchaBind.getClientId(), errMsg);
            }
        }
    

  • Again run this application and enter value for captcha



  • So it is working , now to change captcha image added a link with partialSubmit=false and set partial trigger property on af:image.


  • Kaptcha integration with Oracle ADF is complete and it is working properly  now if you want to modify captcha look n feel then add some init-param (configuration parameter) in web.xml file.
    See complete list of configuration parameters- https://code.google.com/p/kaptcha/wiki/ConfigParameters
    I have changed some parameters value in web.xml , see changed source of web.xml and captcha output

  • <servlet>
            <servlet-name>Kaptcha</servlet-name>
            <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
            <init-param>
                <param-name>kaptcha.border</param-name>
                <param-value>yes</param-value>
            </init-param>
            <init-param>
                <param-name>kaptcha.border.color</param-name>
                <param-value>red</param-value>
            </init-param>
            <init-param>
                <param-name>kaptcha.border.thickness</param-name>
                <param-value>1</param-value>
            </init-param>
            <init-param>
                <param-name>kaptcha.image.width</param-name>
                <param-value>250</param-value>
            </init-param>
            <init-param>
                <param-name>kaptcha.image.height</param-name>
                <param-value>60</param-value>
            </init-param>
            <init-param>
                <param-name>kaptcha.textproducer.font.size</param-name>
                <param-value>35</param-value>
            </init-param>
            <init-param>
                <param-name>kaptcha.textproducer.font.color</param-name>
                <param-value>red</param-value>
            </init-param>
            <init-param>
                <param-name>kaptcha.background.clear.from</param-name>
                <param-value>orange</param-value>
            </init-param>
            <init-param>
                <param-name>kaptcha.textproducer.char.length</param-name>
                <param-value>7</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>Kaptcha</servlet-name>
            <url-pattern>/kaptchaimage</url-pattern>
        </servlet-mapping>
    

    again run this application and check output

    Thanks, Happy Learning :)
    Download-Sample ADF Application

3 comments :

  1. Hi Ashish,
    Refresh link is not working IE , would you please check ?
    It is working perfectly in chrome.

    ReplyDelete
  2. FYI.

    I found the solution for IE.The error is because of IE cache system So I have append the current date at the time of calling servlet Url.Internet Explorer, in its wisdom, will automatically cache responses from GET requests while other browsers will let you decide if you’d like to cache the result or not. Once IE has successfully made a GET request, it will no longer even make that AJAX call until the cache expires on that object

    image source="/kaptchaimage?version=#{currentDate}" id="i1" partialTriggers="l1"
    shortDesc="Captcha"

    Thanks,

    ReplyDelete
    Replies
    1. Nice catch Sandeep and Thanks for Sharing :)

      Delete