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.