|
|
## Introducción
|
|
|
Con el objetivo de evitar los mensajes de Spam, reCaptcha examina pistas no escritas de cada usuario, como la dirección IP o las cookies activas y a través de un algoritmo comprueba nuestro comportamiento a través de Internet, asegurandóse de que somos ese humano al que las cookies han estado siguiendo mientras navegaba. Más allá de eso, el Algoritmo también tendrá en cuenta lo que hacemos cuando nos aparece la caja de reCaptcha, es decir, registra el movimiento de nuestro mouse para ver cómo nos comportamos cuando aparece el reCaptcha. Los bots suelen hacerlo de una manera automática.
|
|
|
|
|
|
Para más información ver el siguiente artículo de Genbeta [Cómo reCaptcha sabe que "eres un humano y no un robot" con solo marcar una casilla](https://www.genbeta.com/a-fondo/como-recaptcha-sabe-que-eres-un-humano-y-no-un-robot-con-solo-marcar-una-casilla)
|
|
|
|
|
|
## Registrar reCaptcha de nuestro sitio
|
|
|
Primero que debe hacer es ir a Google reCAPTCHA e inscribirse. Después de eso, obtendrá un SiteKey que se utiliza para mostrar el widget reCaptcha en sus páginas web. También recibirá un SecretKey que debe mantenerse en secreto y utilizarse para comunicarse con el servidor de Google para verificar la respuesta de captcha.
|
|
|
|
|
|
Registrarse con la cuenta de google en: <https://www.google.com/recaptcha/intro/v3.html>
|
|
|
|
|
|
## Implementar reCaptcha en JSPUI
|
|
|
Para realizar este tutorial me basé en:
|
|
|
- [Merge de Nelson Torres para el dspace de Universidade U Minho](https://gitlab.fccn.pt/ntorres/dspace/commit/500370208c37f70f430104f0851e1d33beaff3b5)
|
|
|
- [Documentación de Google](https://developers.google.com/recaptcha/intro)
|
|
|
- [Commit de Anu-DOI](https://github.com/anu-doi/DSpace/commit/bf6fde11d5b9356eb4490053dbe18ba1ef37a39d)
|
|
|
|
|
|
### Modificar el archivo dspace.cfg y local.cfg
|
|
|
En un ambiente de desarrollo, es decir, donde utilicemos localhost para probar nuestro código, podremos utilizar unas claves que nos ofrece Google en <https://developers.google.com/recaptcha/docs/faq#id-like-to-run-automated-tests-with-recaptcha.-what-should-i-do>
|
|
|
|
|
|
Agregar al final del archivo `dspace.cfg`
|
|
|
|
|
|
```xml
|
|
|
###########################
|
|
|
# RECAPTCHA CONFIGURATION #
|
|
|
###########################
|
|
|
recaptcha.sitekey = ${recaptcha.sitekey}
|
|
|
recaptcha.secretkey = ${recaptcha.secretkey}
|
|
|
recaptcha.siteverify = ${recaptcha.siteverify}
|
|
|
recaptcha.enabled = ${recaptcha.enabled}
|
|
|
```
|
|
|
|
|
|
En nuestro archivo de variables de entorno (local.cfg o build.properties) pondremos al final
|
|
|
|
|
|
```xml
|
|
|
###########################
|
|
|
# RECAPTCHA CONFIGURATION #
|
|
|
###########################
|
|
|
recaptcha.sitekey = 6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI
|
|
|
recaptcha.secretkey = 6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe
|
|
|
recaptcha.siteverify = https://www.google.com/recaptcha/api/siteverify
|
|
|
recaptcha.enabled = true
|
|
|
```
|
|
|
|
|
|
> Nota: cambiar las claves sitekey y secretkey en el ambiente de produccion por las obtenidas en el paso anterior.
|
|
|
|
|
|
### Crear clases de java para el reCaptcha v2
|
|
|
Como primer paso deberemos crear el directorio `dspace/modules/additions/src/main/java/org/dspace/recaptcha/`
|
|
|
|
|
|
#### RecaptchaResponse
|
|
|
Clase que almacena la estructura del API Response
|
|
|
|
|
|
```java
|
|
|
package org.dspace.recaptcha;
|
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
import com.google.gson.annotations.SerializedName;
|
|
|
|
|
|
public class RecaptchaResponse {
|
|
|
String success;
|
|
|
String challenge_ts;
|
|
|
String hostname;
|
|
|
@SerializedName("error-codes")
|
|
|
List<String> errorCodes;
|
|
|
|
|
|
public String getSuccess() {
|
|
|
return success;
|
|
|
}
|
|
|
|
|
|
public void setSuccess(String success) {
|
|
|
this.success = success;
|
|
|
}
|
|
|
|
|
|
public String getChallenge_ts() {
|
|
|
return challenge_ts;
|
|
|
}
|
|
|
|
|
|
public void setChallenge_ts(String challenge_ts) {
|
|
|
this.challenge_ts = challenge_ts;
|
|
|
}
|
|
|
|
|
|
public String getHostname() {
|
|
|
return hostname;
|
|
|
}
|
|
|
|
|
|
public void setHostname(String hostname) {
|
|
|
this.hostname = hostname;
|
|
|
}
|
|
|
|
|
|
public List<String> getErrorCodes() {
|
|
|
return errorCodes;
|
|
|
}
|
|
|
|
|
|
public void setErrorCodes(List<String> errorCodes) {
|
|
|
this.errorCodes = errorCodes;
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### RecaptchaQuery
|
|
|
Se encarga de la verificación del reCaptcha
|
|
|
|
|
|
```java
|
|
|
package org.dspace.recaptcha;
|
|
|
|
|
|
import com.google.gson.Gson;
|
|
|
import org.apache.http.HttpEntity;
|
|
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
|
|
import org.apache.http.client.methods.HttpPost;
|
|
|
import org.apache.http.client.utils.URIBuilder;
|
|
|
import org.apache.http.impl.client.CloseableHttpClient;
|
|
|
import org.apache.http.impl.client.HttpClients;
|
|
|
import org.apache.log4j.Logger;
|
|
|
import org.dspace.authorize.AuthorizeException;
|
|
|
import org.dspace.core.ConfigurationManager;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
import java.io.InputStream;
|
|
|
import java.io.InputStreamReader;
|
|
|
import java.io.Reader;
|
|
|
import java.net.URISyntaxException;
|
|
|
|
|
|
public class RecaptchaQuery {
|
|
|
private static final Logger log = Logger.getLogger(RecaptchaQuery.class);
|
|
|
private static String secret = ConfigurationManager.getProperty("recaptcha.secretkey");
|
|
|
private static String siteverify = ConfigurationManager.getProperty("recaptcha.siteverify");
|
|
|
private static boolean recaptchaEnabled = ConfigurationManager.getBooleanProperty("recaptcha.enabled");
|
|
|
|
|
|
public RecaptchaResponse query(String token) throws URISyntaxException, IOException {
|
|
|
|
|
|
URIBuilder uriBuilder = new URIBuilder(siteverify);
|
|
|
|
|
|
uriBuilder.addParameter("secret", secret);
|
|
|
uriBuilder.addParameter("response", token);
|
|
|
|
|
|
HttpPost post = new HttpPost(uriBuilder.build());
|
|
|
|
|
|
CloseableHttpClient client = HttpClients.createDefault();
|
|
|
|
|
|
CloseableHttpResponse response = client.execute(post);
|
|
|
|
|
|
HttpEntity responseEntity = response.getEntity();
|
|
|
InputStream is = responseEntity.getContent();
|
|
|
|
|
|
Reader reader = new InputStreamReader(is, "UTF-8");
|
|
|
Gson gson = new Gson();
|
|
|
RecaptchaResponse captchaResponse = gson.fromJson(reader, RecaptchaResponse.class);
|
|
|
|
|
|
return captchaResponse;
|
|
|
}
|
|
|
|
|
|
public static boolean verify(String gRecaptchaResponse) {
|
|
|
// Start Recaptcha form
|
|
|
boolean verifyRecaptcha = false;
|
|
|
|
|
|
if (recaptchaEnabled) {
|
|
|
if(secret == null || secret.equals("")) {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
if (gRecaptchaResponse == null || gRecaptchaResponse.equals("")) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
RecaptchaQuery query = new RecaptchaQuery();
|
|
|
try {
|
|
|
RecaptchaResponse captchaResponse = query.query(gRecaptchaResponse);
|
|
|
log.info("Request item captcha response: "
|
|
|
+ captchaResponse.getSuccess()
|
|
|
+ ", "
|
|
|
+ captchaResponse.getChallenge_ts()
|
|
|
+ ", "
|
|
|
+ captchaResponse.getHostname()
|
|
|
+ ", "
|
|
|
+ captchaResponse.getErrorCodes()
|
|
|
);
|
|
|
if ("false".equals(captchaResponse.getSuccess())) {
|
|
|
log.error("Recaptcha returned a negative response");
|
|
|
throw new AuthorizeException("You have not been authorised to request an items files");
|
|
|
}
|
|
|
verifyRecaptcha = Boolean.parseBoolean(captchaResponse.getSuccess());
|
|
|
}
|
|
|
catch (IOException | URISyntaxException | AuthorizeException e) {
|
|
|
log.error("Exception processing re-captcha response");
|
|
|
verifyRecaptcha = false;
|
|
|
}
|
|
|
} else {
|
|
|
verifyRecaptcha = true;
|
|
|
}
|
|
|
// End Recaptcha form
|
|
|
return verifyRecaptcha;
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### Implementar reCaptcah en el formulario Feedback de DSpace
|
|
|
En el archivo `dspace/modules/jspui/src/main/webapp/feedback/form.jsp` agregar:
|
|
|
|
|
|
```jsp
|
|
|
<%@ page import="org.dspace.core.ConfigurationManager" %>
|
|
|
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
|
|
|
<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %>
|
|
|
|
|
|
<%
|
|
|
...
|
|
|
|
|
|
// Recaptcha
|
|
|
boolean recaptchaEnabled = ConfigurationManager.getBooleanProperty("recaptcha.enabled");
|
|
|
String recpatchaSiteKey = ConfigurationManager.getProperty("recaptcha.sitekey");
|
|
|
%>
|
|
|
<dspace:layout titlekey="jsp.feedback.form.title">
|
|
|
...
|
|
|
<% if(recaptchaEnabled) { %>
|
|
|
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
|
|
|
<div class="g-recaptcha" data-sitekey="<%= recpatchaSiteKey %>"></div>
|
|
|
<% } %>
|
|
|
...
|
|
|
</dspace:layout>
|
|
|
```
|
|
|
|
|
|
> Nota: tener en cuenta la estructura de HTML del formulario. El div "g-recpatcha" va antes del botón que envia el formulario
|
|
|
|
|
|
Por otro lado, en el archivo `dspace/modules/jspui/src/main/java/org/dspace/app/webui/servlet/FeedbackServlet.java` (si no existe copiarlo del modulo dspace-jspui) agregar:
|
|
|
|
|
|
```java
|
|
|
import org.dspace.recaptcha.RecaptchaQuery;
|
|
|
...
|
|
|
// Has the user just posted their feedback?
|
|
|
if (request.getParameter("submit") != null)
|
|
|
{
|
|
|
EmailValidator ev = EmailValidator.getInstance();
|
|
|
String feedback = request.getParameter("feedback");
|
|
|
|
|
|
// Start Recaptcha
|
|
|
String gRecaptchaResponse = request.getParameter("g-recaptcha-response");
|
|
|
boolean verify = RecaptchaQuery.verify(gRecaptchaResponse);
|
|
|
// End Recaptcha
|
|
|
|
|
|
// Check all data is there
|
|
|
if ((formEmail == null) || formEmail.equals("")
|
|
|
|| (feedback == null) || feedback.equals("") || !ev.isValid(formEmail) || !verify)
|
|
|
{
|
|
|
request.setAttribute("email", formEmail);
|
|
|
request.setAttribute("feedback", feedback);
|
|
|
request.setAttribute("fromPage", fromPage);
|
|
|
|
|
|
log.info(LogManager.getHeader(context, "show_feedback_form",
|
|
|
"problem=true"));
|
|
|
request.setAttribute("feedback.problem", Boolean.TRUE);
|
|
|
JSPManager.showJSP(request, response, "/feedback/form.jsp");
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
...
|
|
|
}
|
|
|
```
|
|
|
|
|
|
Para más información, ver el commit:
|
|
|
|