Actualización marzo del 2019: coinhive ha dejado de funcionar o dejará de funcionar al momento de escribir este post; por lo tanto este captcha ya no es válido.
Nota: si quieres usar reCAPTCHA en PHP mira mi otro post. Sé que este post es sobre una alternativa a reCAPTCHA pero como puedes ver, ya no funciona.
Sordid details following…
Un captcha funciona principalmente para detener a los bots y dejar pasar a los humanos. Veamos cómo trabajar con el captcha de coinhive en PHP.
El captcha de coinhive es un captcha como el recaptcha de Google, pero éste funciona minando criptomonedas. Así, no medimos si se trata de una persona o de un bot, sino del poder computacional.
Gracias a esto, a los “spammers” no les funcionará programar bots, pues aunque el captcha no ofrece retos para los bots, hace que la computadora tenga que trabajar. De esta forma los bots tendrán que esperar bastante tiempo antes de hacer lo que iban a hacer.
Esto es muy sencillo. Lo que tenemos que hacer es poner el captcha dentro de un formulario. Cuando el captcha detecta que has resuelto los hashes correspondientes, inyecta un nuevo campo al formulario, el cual tiene un token.
Del lado del servidor comprobamos el token con la API de coinhive, y si ambos coinciden entonces significa que el captcha ha sido resuelto correctamente.
Comencemos programando el lado del cliente para trabajar con el captcha de coinhive en PHP.
Pongamos de ejemplo este formulario en donde simplemente pedimos un nombre:
<form method="post" action="comprobar.php">
<input type="text" name="nombre" placeholder="Escribe tu nombre">
<input type="submit" value="Enviar">
</form>
Ahora, para integrar el captcha ponemos dentro de él la carga del script y el siguiente div:
<script src="https://authedmine.com/lib/captcha.min.js" async></script>
<div
data-disable-elements="[type='submit']"
data-whitelabel="true"
class="coinhive-captcha"
data-hashes="1024"
data-key="clave">
<div>
Esto se muestra mientras el captcha carga
</div>
</div>
Expliquemos los atributos:
La lista completa así como la guía la podemos ver en: https://coinhive.com/documentation/captcha
Es importante notar que si el usuario tiene un bloqueador de publicidad el script no se cargará, y por lo tanto no será posible resolver el captcha.
De tal manera que nuestro formulario completo lucirá así (por favor ignorar los estilos por ahora, pues el objetivo del post no es ese):
<form method="post" action="comprobar.php">
<input type="text" name="nombre" placeholder="Escribe tu nombre">
<br>
<br>
<script src="https://authedmine.com/lib/captcha.min.js" async></script>
<div
data-disable-elements="[type='submit']"
data-whitelabel="true"
class="coinhive-captcha"
data-hashes="1024"
data-key="clave">
<div>
Esto se muestra mientras el captcha carga
</div>
</div>
<br>
<input type="submit" value="Enviar">
</form>
Veamos ahora el lado del servidor.
Sigamos ahora con el lado del servidor para trabajar con el captcha de coinhive en PHP.
En el lado del servidor recibiremos el nombre y el token. Como lo dije, se enviará por el método post y podremos acceder a él a través de $_POST["coinhive-captcha-token"]
.
El código de ejemplo queda así:
<?php
$datos = [
'secret' => 'clave_privada', # clave privada. Obtener de coinhive
'token' => isset($_POST["coinhive-captcha-token"]) ? $_POST["coinhive-captcha-token"] : "", # el valor que recibimos del formulario. Poner modo por defecto si no lo mandan
'hashes' => 1024, # el mismo número que pusimos en el formulario
];
$contexto = stream_context_create([
'http' => [
'header' => "Content-type: application/x-www-form-urlencoded\r\n", #Encabezados, dejar así
'method' => 'POST', # El método
'content' => http_build_query($datos) # Formamos la cadena de datos a enviar
]
]);
$url = 'https://api.coinhive.com/token/verify'; #Aquí se envían las peticiones
$respuesta = json_decode(file_get_contents($url, false, $contexto)); # Hacemos la petición POST
/*
La API devuelve un JSON. Lo decodificamos con json_decode y vemos si
no es NULL y si tiene una propiedad llamada success con el valor
true. En caso de que sí, adelante, el usuario ha
resuelto el captcha.
Si no (ya sea porque no se esperó, envió el formulario antes o
no resolvió los hashes esperados) entonces no lo dejamos pasar
*/if($respuesta && $respuesta->success){
echo "Ok, pasa " . $_POST["nombre"]; #Ejemplo de lo que hacemos si todo va bien
}else{
echo "¡Alto ahí rufián!"
}
?>
Lo que hacemos es hacer una petición post con stream_context_create
. Le pasamos nuestra clave privada (no la pública, ya que la pública va en el formulario), los hashes que pusimos del lado del cliente para evitar trampas y también el token que debió ser generado por el captcha.
De ahí coinhive se encarga de realizar la validación y dependiendo de ello nosotros realizamos acciones.
Obviamente este es un ejemplo básico, no hay validaciones ni estilos, pero muestra lo más importante de cómo trabajar con este servicio que algunos llaman malware aunque no lo es 😉
Hoy te voy a presentar un creador de credenciales que acabo de programar y que…
Ya te enseñé cómo convertir una aplicación web de Vue 3 en una PWA. Al…
En este artículo voy a documentar la arquitectura que yo utilizo al trabajar con WebAssembly…
En un artículo anterior te enseñé a crear un PWA. Al final, cualquier aplicación que…
Al usar Comlink para trabajar con los workers usando JavaScript me han aparecido algunos errores…
En este artículo te voy a enseñar cómo usar un "top level await" esperando a…
Esta web usa cookies.
Ver comentarios
tu idea es buena, pero tu demo toma mil años minar los 1024 hash, no hay algo mas rapido?, gracias.
Hola. Justamente el propósito de este captcha es que sea tardado; prueba minando 256 hashes a ver qué tal; recuerda que todo depende de la máquina.
El resultado es el mismo, incluso con cero, tarda menos , pero tarda mucho todavía y corro el riesgo de que el usuario se desespere y se vaya.
Tienes razón, el usuario puede abandonar la página. Recuerda que únicamente es una alternativa, de ahí puedes seguir usando recaptcha. Por otro lado, te digo de nuevo que depende de la computadora del usuario, prueba en otra PC y verás.
Gracias, hice la prueba en otra computadora con mayor capacidad y ahora tardó unos 30 segundos contra como 5 minutos en la anterior, veo que esto no es viable para equipos con pocas prestaciones, seguiré con recaptcha mejor, saludos.
Sí, te digo que depende mucho de la computadora. En mi caso la mía (y no es nada potente, sirve para lo básico) tarda como 32 segundos para calcular 1024 hashes.