Thursday, June 11, 2020

Using Google reCAPTCHA with ADF Application

From this article, that illustrates how to implement Google's free CAPTCHA service in java web application, it's easy to implement it in one ADF Application.

First you need to sign up your site on Google reCAPTCHA, specifying the domains where it is hosted and the type of captcha to display.

https://www.google.com/recaptcha/admin?hl=en



After successful registration Site-Key and Secret-Key have been provided.



This information are stored in a java class MyConstants as final variables.

In the ViewController project you create a bounded task flow to implement captcha on page fragments and run it as region in .jsf page. This page need to include javascript API to render and use captcha.
 
<af:resource type="javascript"
                     source="https://www.google.com/recaptcha/api.js"></af:resource>

In the form that must be secured, the captcha is rendered in a div tag; this tag must use g-recaptcha class and and have a data-sitekey attribute with the site-key previously generated.
 
<!-- reCAPTCHA -->
<div class="g-recaptcha" data-sitekey="6LcVOaMZAAAAACiTMHlhWJPNEMuxP3oGM2m9B2ox"
             xmlns="http://www.w3.org/1999/xhtml">


When the user check captcha, reCAPTCHA API generates an authentication code that is hosted in the request attribute g-recaptcha-response. When the user submit the form, at the server a request containig the authentication code and the site's secret-key will be created and submitted to Google reCAPTCHA service to validate it.



To use Google reCAPTCHA service, you need to import JAX-RS Jersey 2.x Client library in the ViewController project. The following code is responsable to generate and submit the request to Google reCAPTCHA service.

public static final String SITE_VERIFY_URL = 
"https://www.google.com/recaptcha/api/siteverify";
 
public static boolean verify(String gRecaptchaResponse) {
    if (gRecaptchaResponse == null || gRecaptchaResponse.length() == 0) {
        return false;
    }
 
    try {
        URL verifyUrl = new URL(SITE_VERIFY_URL);
        // Open a Connection to URL above.
        URLConnection connection = verifyUrl.openConnection();
        // Add the Header informations to the Request to prepare send to the server.
        connection.setDoOutput(true); // Triggers POST
        connection.setRequestProperty("User-Agent", "Mozilla/5.0");
        connection.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
        // Data will be sent to the server.
        String postParams = "secret=" + MyConstants.SECRET_KEY //
           + "&response=" + gRecaptchaResponse;
 
        // Send Request
        connection.setDoOutput(true);
        // Get the output stream of Connection.
        // Write data in this stream, which means to send data to Server.
        OutputStream outStream = connection.getOutputStream();
        outStream.write(postParams.getBytes());
        outStream.flush();
        outStream.close();
 
        // Get the Input Stream of Connection to read data sent from the Server.
        InputStream is = connection.getInputStream();
        JsonReader jsonReader = Json.createReader(is);
        JsonObject jsonObject = jsonReader.readObject();
        jsonReader.close();
 
        // ==> {"success": true}
        System.out.println("Response: " + jsonObject);
 
        boolean success = jsonObject.getBoolean("success");
        return success;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}
  
Using this method in a managed been with page flow scope, it's possible to use captcha to secure a form submission. In the following code is shown how get the authentication code and validate it with verify method, shown above.

public void onSubmit(ActionEvent actionEvent) {
    String reCaptchaResponse = FacesContext.getCurrentInstance()
                                          .getExternalContext()
                                          .getRequestParameterMap().get("g-recaptcha-response");
    System.out.println(reCaptchaResponse);
    if(reCaptchaResponse != null && !reCaptchaResponse.equals("")){
       boolean valid = VerifyUtils.verify(reCaptchaResponse);
       if(!valid)
           reCaptchaInvalid = true;
        else
           reCaptchaInvalid = false;
    } else {
        reCaptchaInvalid = true;    
    }
}






No comments:

Post a Comment