Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

Implementei um exemplo JSF com reCAPTCHA v2 e funcionou corretamente porem com o reCAPTCHA v3 nao funcionou

Implementei um exemplo JSF com reCAPTCHA v2 e funcionou corretamente

Tentei implementar com o reCAPTCHA v3 usando o modelo indicado na documentação do site do Google Recaptcha (https://developers.google.com/recaptcha/docs/v3) e não funcionou, alguem conseguiu fazer o V3 funcionar?

DESSE JEITO NAO FUNCIONOU COM O V3 UTILIZANDO UM BUTTON:

 <script src="https://www.google.com/recaptcha/api.js"></script>
 <script>
   function onSubmit(token) {
     document.getElementById("demo-form").submit();
   }
 </script>

<button class="g-recaptcha" 
        data-sitekey="reCAPTCHA_site_key" 
        data-callback='onSubmit' 
        data-action='submit'>Submit</button>

O QUE FUNCIONOU FOI FAZENDO COM O V2 UTILIZANDO UMA DIV:

[index.xhtml]
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
        <title>GoogleRecaptchaTeste_V2_XHTML_JSF Login Page</title>
        <script src="https://www.google.com/recaptcha/api.js"></script>
    </h:head>
    <h:body>

            <h:form  >
                    <h1>GoogleRecaptchaTeste_V2_XHTML_JSF</h1>
                    <br/> 

                    <h:outputLabel value="Username: " /> 
                    <p:inputText value="#{managedBeanLogin.user}" /> <br/>
                    <br/>                    
                    <h:outputLabel value="Password: " />
                    <p:inputText value="#{managedBeanLogin.pwd}" />
                    <br/>

                    <p:messages id="pmessages"/>                    
                    <br/>                    
                    <div id="google-recaptcha" class="g-recaptcha" data-sitekey="minhaChaveSiteCadastradaNoGoogleRecaptcha"> </div>  <br/>
                    <br/> 

                    <p:commandButton value="Login" action="${loginController.login}" ajax="false"/>
                    <br/>
                    <br/>

                    <span style="font-size: smaller">(hint: root admin)</span>

                    <br/> 
                    <br/> 
                    <br/> 
                    Dica: Observe no console terminal de saida do tomcat as chamadas a API do google recaptcha
                    <br/> 
                    <br/> 
                    <br/> 
                    <h2>
                        <a href="http://www.google.com.br" target="_blank">www.google.com.br</a>
                    </h2>
                    <br/> 
                    <br/> 
            </h:form>
</h:body>
</html>
@ManagedBean
public class LoginController implements Serializable{

    public String login() throws IOException{
        try {
            System.out.println("...executando metodo LoginController.login()");

            ManagedBeanLogin managedBeanLogin = (ManagedBeanLogin) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("managedBeanLogin");
            String user = managedBeanLogin==null?"":managedBeanLogin.getUser();
            String pwd = managedBeanLogin==null?"":managedBeanLogin.getPwd();

            String gRecaptchaResponse = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("g-recaptcha-response");
            System.out.println("g-recaptcha-response:");
            System.out.println(gRecaptchaResponse);

            boolean verify = VerifyRecaptcha.verify(gRecaptchaResponse);

            String userID = "root";
            String password = "admin";

            System.out.println("User=" + user + "::password=" + pwd + "::Captcha Verify"+verify);
public class VerifyRecaptcha {

    public static final String url = "https://www.google.com/recaptcha/api/siteverify";
    public static final String secret = "minhaChavePrivadaCadastradaNoGoogleRecaptc";
    private final static String USER_AGENT = "Mozilla/5.0";

    public static boolean verify(String gRecaptchaResponse) throws IOException {

        if (gRecaptchaResponse == null || "".equals(gRecaptchaResponse)) {
            return false;
        }

        try {
            URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();

            // add reuqest header
            con.setRequestMethod("POST");
            con.setRequestProperty("User-Agent", USER_AGENT);
            con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
         ...

Alguém consegue ajudar a implementar o reCaptcha V3 nesse código acima ???

3 respostas

Olá Hemerson, tudo bem?

Acredito que o importe tenha que ser assim:

<script src="https://www.google.com/recaptcha/api.js?render=reCAPTCHA_site_key"></script>

Note que você deve substituir reCAPTCHA_site_key pelo seu site key, que você obteve ao registrar o seu site junto ao serviço do reCAPTCHA.

E na função login() do seu LoginController, crie uma chamada ao endpoint https://www.google.com/recaptcha/api/siteverify passando o g-recaptcha-response que você recebeu do formulário, junto com a sua chave privada do reCAPTCHA V3. Aqui está um exemplo:

public String login() throws IOException {
    ManagedBeanLogin managedBeanLogin = (ManagedBeanLogin) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("managedBeanLogin");
    String user = managedBeanLogin == null ? "" : managedBeanLogin.getUser();
    String pwd = managedBeanLogin == null ? "" : managedBeanLogin.getPwd();

    String gRecaptchaResponse = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("g-recaptcha-response");
    System.out.println("g-recaptcha-response:");
    System.out.println(gRecaptchaResponse);

    String secret = "minhaChavePrivadaCadastradaNoGoogleRecaptc";
    URL obj = new URL("https://www.google.com/recaptcha/api/siteverify");
    HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();

    // add reuqest header
    con.setRequestMethod("POST");
    con.setRequestProperty("User-Agent", "Mozilla/5.0");
    con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");

    String postParams = "secret=" + secret + "&response=" + gRecaptchaResponse;

    // Send post request
    con.setDoOutput(true);
    DataOutputStream wr = new DataOutputStream(con.getOutputStream());
    wr.writeBytes(postParams);
    wr.flush();
    wr.close();

    int responseCode = con.getResponseCode();
    System.out.println("Sending 'POST' request to URL : " + obj);
    System.out.println("Post parameters : " + postParams);
    System.out.println("Response Code : " + responseCode);

    BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
    String inputLine;
    StringBuffer response = new StringBuffer();

    while ((inputLine = in.readLine()) != null) {
        response.append(inputLine);
    }
    in.close();

    // print result
    System.out.println(response.toString());

    // Check reCAPTCHA response and proceed with login logic
    JsonObject jsonObject = Json.createReader(new StringReader(response.toString())).readObject();
    boolean verify = jsonObject.getBoolean("success");

    String userID = "root";
    String password = "admin";

    System.out.println("User=" + user + "::password=" + pwd + "::Captcha Verify" + verify);
    // Rest of login logic goes here

    return null;
}

Em vez de adicionar a classe g-recaptcha a um botão, como você fez para o reCAPTCHA V2, agora você deve chamar a função grecaptcha.execute() do reCAPTCHA V3 na sua página.

Olá Otávio,

Tudo bem sim e com você ?

Se não foi incomodo, consegue colocar um pequeno código como exemplo ?

Desde já agradeço

solução!

Adicione uma chamada para renderizar o reCAPTCHA V3 em algum lugar da página: html

<div id="recaptcha-container"></div>

Substitua o método VerifyRecaptcha.verify() pelo seguinte código:

public static boolean verify(String gRecaptchaResponse) throws IOException {

    if (gRecaptchaResponse == null || "".equals(gRecaptchaResponse)) {
        return false;
    }

    try {
        URL obj = new URL(url);
        HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();

        // add reuqest header
        con.setRequestMethod("POST");
        con.setRequestProperty("User-Agent", USER_AGENT);
        con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");

        String postParams = "secret=" + secret + "&response=" + gRecaptchaResponse;

        // Send post request
        con.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(con.getOutputStream());
        wr.writeBytes(postParams);
        wr.flush();
        wr.close();

        int responseCode = con.getResponseCode();
        System.out.println("\nSending 'POST' request to URL : " + url);
        System.out.println("Post parameters : " + postParams);
        System.out.println("Response Code : " + responseCode);

        BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();

        // Parse JSON response and check score
        JSONObject json = new JSONObject(response.toString());
        double score = json.getDouble("score");
        System.out.println("Score: " + score);
        return score >= 0.5;

    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

O código acima envia a chave secreta do reCAPTCHA V3 e a resposta do reCAPTCHA para o endpoint de verificação, obtém a resposta JSON e verifica o score. Nesse exemplo, a verificação é considerada aprovada se o score for igual ou superior a 0.5.

E adicione o seguinte código JS no final da página para renderizar o reCAPTCHA V3 e obter a resposta:

<script>
grecaptcha.ready(function() {
    grecaptcha.execute('reCAPTCHA_site_key', {action: 'submit'}).then(function(token) {
        document.getElementById('g-recaptcha-response').value = token;
        document.getElementById('demo-form').submit();
    });
});
</script>

Substitua reCAPTCHA_site_key pelo seu site key do reCAPTCHA V3.

O código acima renderiza o reCAPTCHA V3 e obtém a resposta (o token) quando o usuário submete o formulário.