Expand my Community achievements bar.

Using OOTB-style Constraints in AEM on a Custom Form Component

Avatar

Level 1

I'm trying to validate a custom recaptcha component using constraints in the same way the OOTB Form Elements do.  I'm having trouble figuring out how to connect the custom component to it's servervalidation.jsp though.

I need help getting to the point where submitting a form with the custom constraint selected causes the captcha/servervalidations.jsp to validate.  It currently allows an undone captcha to be submitted.

I have my component:

(I made a lot of edits to the captcha.jsp for brevity here since it's not really the point and I may have messed it up, so if there's syntax errors in that file don't worry about it.)

captcha.jsp

    <%@include file="/apps/codebase/global.jsp" %>

  

    <div class="captcha-wrap">

      <div id="recaptcha${properties.reCaptchaId}" class="g-recaptcha"></div>  

    <script>

  

        /* Renders captchas.  Runs @ async defer (callback on recaptcha src script in 'basepage/footer.jsp') */

        function recaptchaCallback() {

          var cC = $('.g-recaptcha').length;  // captcha count

          if ( cC >= 1 && cC <= 6) {   // recaptcha1 loads when cC is 1-6

            grecaptcha.render('recaptcha1', {

              'sitekey' : '<PUBLIC_KEY>'

            });

          }

          if ( cC >= 2 && cC <=  6) {

            grecaptcha.render('recaptcha2', {

              'sitekey' : '<PUBLIC_KEY>'

            });

          }

          /* Additional if statements for rendering 1 to 6 captchas on the same page */

  

    </script>

This script renders the captcha:

footer.jsp

    <script src="https://www.google.com/recaptcha/api.js?onload=recaptchaCallback&render=explicit" defer></script>

Here is my dialog with the OOTB captcha constraint tab included

dialog.xml

    <?xml version="1.0" encoding="UTF-8"?>

    <jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"

        jcr:primaryType="cq:Dialog"

        title="Captcha Configuration"

        xtype="dialog">

        <items

            jcr:primaryType="cq:Widget"

            xtype="tabpanel">

            <items jcr:primaryType="cq:WidgetCollection">

                <tab0

                    jcr:primaryType="cq:Panel"

                    title="Captcha">

                    <items jcr:primaryType="cq:WidgetCollection">

                        <reCaptchaId

                        jcr:primaryType="cq:Widget"

                        fieldDescription="Must be 1, 2, 3, 4, 5 or 6. Must go in order, i.e. don't only have a 1, 2, and 4 on the page or it won't work. Will not work with 7+ either."

                        fieldLabel="ReCaptcha ID"

                        name="./reCaptchaId"

                        xtype="textfield" />

                    </items>

                </tab0>

            <tab1

               jcr:primaryType="nt:unstructured"

               title="Constraints"

               xtype="panel">

               <items jcr:primaryType="cq:WidgetCollection">

                    <required

                         jcr:primaryType="cq:Widget"

                         fieldLabel="Required"

                         inputValue="true"

                         name="./required"

                         type="checkbox"

                         xtype="selection"/>

                   <requiredMessage

                         jcr:primaryType="cq:Widget"             

                         fieldLabel="Required Message"

                         name="./requiredMessage"

                         xtype="textarea"/>

                    <constraintType

                         jcr:primaryType="cq:Widget"

                         fieldLabel="Constraint"

                         name="./constraintType"

                         options="/etc/designs/codebase/options/constraints.json"

                         type="select"

                         xtype="selection"/>

                   <constraintMessage

                        jcr:primaryType="cq:Widget"

                        fieldLabel="Constraint Message"

                        name="./constraintMessage"

                        xtype="textarea"/>

                </items>

             </tab1> 

            </items>

        </items>

    </jcr:root>

And here is the json referenced:

constraints.json

    [

         {"value":"","text":"None"},

         {"value":"codebase/components/content/formelements/constraints/captcha","text":"Captcha"}

    ]

Which brings me to the constraint file itself.  My problem is that I cannot get this file to actually validate against the captcha.jsp file.  So it has not been debugged and may be full of java errors for all I know.

This file is a combination of the OOTB file found at /libs/foundation/components/form/captcha/servervalidation.jsp<br>

and the captcha validation solution found here: Server side validation for reCAPTCHA V2 or Invisible reCAPTCHA with Java (Servlet) - Code Review Sta...

codebase/components/content/formelements/constraints/captcha/servervalidation.jsp

    <%@page session="false" %><%

    %><%@page import="java.io.BufferedReader,

    java.io.InputStream;

                    java.text.ParsePosition,

        java.io.InputStreamReader,

    java.net.URL,

    java.nio.charset.Charset,

    org.json.JSONObject,

                    com.day.cq.wcm.foundation.forms.FieldHelper,

                    com.day.cq.wcm.foundation.forms.FieldDescription,

                    com.day.cq.wcm.foundation.forms.FormsHelper,

                    com.day.cq.wcm.foundation.forms.ValidationInfo"%><%

    %><%@taglib prefix="sling" uri="http://sling.apache.org/taglibs/sling/1.0" %>

  

    <sling:defineObjects/><%

  

        // Get field description and force its name

        FieldDescription desc = FieldHelper.getConstraintFieldDescription(slingRequest);

        desc.setName(":cq:recaptcha");

  

        // Check if a value has been provided

        if (FieldHelper.checkRequired(slingRequest, desc)) {

            final String response = request.getParameter("g-recaptcha-response");

            final String secretKey = "<PRIVATE_KEY>";

  

    private static boolean isCaptchaValid(String secretKey, String response) {

        try {

            String url = "https://www.google.com/recaptcha/api/siteverify?"

                    + "secret=" + secretKey

                    + "&response=" + response;

            InputStream res = new URL(url).openStream();

            BufferedReader rd = new BufferedReader(new InputStreamReader(res, Charset.forName("UTF-8")));

  

            StringBuilder sb = new StringBuilder();

            int cp;

            while ((cp = rd.read()) != -1) {

                sb.append((char) cp);

            }

            String jsonText = sb.toString();

            res.close();

  

            JSONObject json = new JSONObject(jsonText);

            return json.getBoolean("success");

        } catch (Exception e) {

            return false;

        }

    }

            if (!isCaptchaValid("<PRIVATE_KEY>", request.getParameter("g-recaptcha-response"))) {

                ValidationInfo.addConstraintError(slingRequest, desc);

            }

        }

  

    %>

How can I get this captcha constraint `servervalidation.jsp` file to actually work? Currently the captcha can be submitted uncompleted and no validation stops it.

I do notice some form parameters in the `_cq_editConfig.xml` of the OOTB components, and that's the only thing I notice that I haven't copied to try to get this constraint to work. But that's because I'm not sure how it works.

11 Replies