reCAPTCHA

Do jednego z moich projektów potrzebowałem wykorzystać Google reCAPTCHA, aby tzw. boty nie zaśmiecały serwisu swoimi wiadomościami. Niby nic trudnego, ale chciałem, aby reCAPTCHA działała w taki sposób, żeby nie przeładowywać strony. Czyli trzeba było też wykorzystać jQuery (mogą też być zapytania ajax’owe). Poniżej przedstawię swój sposób. Część wykorzystałem z innych tutoriali, które można znaleźć w internecie.
Na początku musimy wygenerować sobie klucze reCAPTCHA, które będą nam potrzbne do wpisania w kodzie źródłowym. Możemy je wygenerować na stronie https://www.google.com/recaptcha/intro/index.html klikając w przycisk Get reCAPTCHA. Zostaniemy poproszeni o zalogowanie się na swoje konto Gmail, dzięki czemu będziemy mogli w każdym dowolnym momencie w przyszłości ponownie wykorzystać klucze. Na stronie wypełniamy formularz do pozyskania kluczy.

register-a-new-site

Google wygenerował dla nas dwa klucze: na stronę i sekretny. Najważniejsze jest to, że klucz sekretny nie może być nigdzie widoczny i nikt po za tobą nie może go znać, jest on tylko dla Ciebie.

klucze-recaptcha

Ja wykorzystałem oficjalną bibliotekę do reCAPTCHA, którą możesz pobrać ze strony Using reCAPTCHA with PHP Google Developers. Skoro wszystko już mamy to zabierzmy się do samej implementacji. Na początek utworzymy prosty formularz.


<!DOCTYPE html>
<html>
   <head>
      <title>Learning reCAPTCHA</title>
      <meta charset="utf-8">
   </head>
   <body>
      <form>
         <label for="name">Imię</label>
         <input type="text" id="name" />
         <label for="email">Adres E-mail</label>
         <input type="email" id="email" />
         <label for="message">Wiadomość</label>
         <textarea id="message"></textarea>
         <button type="submit">Wyślij</button>
      </form>
   </body>
</html>

Kolejnym krokiem jest dołączenie do naszego kodu skryptu reCAPTCHA API Google.


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

Oraz wstawienie div’a, w miejsce którego będzie wyświetlało się pole z checkboxem reCAPTCHA.


<div class="g-recaptcha" data-sitekey="6LekyAoTAAAAAJ45flTiqRTwrQPMQuDXCqMpvgRg"></div>

Zauważ, że w atrybucie data-sitekey wpisujemy klucz przeznaczony na stronę (publiczny), bo i tak będzie widoczny w kodzie przez użytkowników.

Ok, mamy podstawy za sobą, czas na skrypty. Utwórzmy sobie plik o nazwie send.js i załączmy go do naszego projektu. Po zmianach nasz kod powinien wyglądać mniej więcej następująco:


<!DOCTYPE html>
<html>
   <head>
      <title>Learning reCAPTCHA</title>
      <meta charset="utf-8">
      <script src="https://www.google.com/recaptcha/api.js"></script>
   </head>
   <body>
      <form>
         <label for="name">Imię</label>
         <input type="text" id="name" />
         <label for="email">Adres E-mail</label>
         <input type="email" id="email" />
         <label for="message">Wiadomość</label>
         <textarea id="message"></textarea>
         <div class="g-recaptcha" data-sitekey="6LekyAoTAAAAAJ45flTiqRTwrQPMQuDXCqMpvgRg"></div>
         <button id="send">Wyślij</button>
      </form>
      <script src="send.js"></script>
   </body>
</html>

W skrypcie send.js wpiszemy funkcje jQuery, która po wciśnięciu przycisku Wyślij utworzy wyśle metodą POST do serwera parametry z formularza włącznie z informacją z reCAPTCHA, a będzie to wyglądało następująco.


$( '#send' ).on( 'click', function() {
   var name = $( '#name' ).val();
   var email = $( '#email' ).val();
   var message = $( '#message' ).val();
   var grecaptcha = $( '.g-recaptcha-response' ).val();

   $.post( 'send-msg.php', { name: name, email: email, message: message, grecaptcha: grecaptcha })
   .success( function( data ) {
      if( data == 'success' ){
         //udało się wysłać wiadomość
      }
      else{
         //błąd wysyłania wiadomości
      }
   })
   .error( function( data ) {
      //błąd połączenia ze skryptem php
   });
});

Co się wydarzyło? Po kolei. Na początku zbieram dane z pól tekstowych (umyślnie nie robię walidacji, bo nie o to chodzi w tym kursie) i przypisuję je do zmiennych lokalnych. Możesz zauważyć, że pobieram informacje z pola $( '.g-recaptcha-response' ). To pole przechowuje klucz jaki skrypt Google wygenerował (żaden z tych, które otrzymaliśmy) na podstawie klucza publicznego. Ten klucz i resztę informacji przesyłamy do skryptu po stronie serwera, który to sprawdzi, czy jest on prawidłowy i czy formularz wypełnił człowiek. Do przesłania informacji do skryptu PHP wykorzystałem metodę jQuery.post, która również posiada metody success, dzięki której pozyskuję zwrócone informacje z serwera i metodę error, gdyby połączenie nie zostało w ogóle nawiązane. W zależności od tego jakie dane zwrotne otrzymam od serwera mogę sobie wykonać różne działania, o czym później.

Następny na naszej liście jest skrypt po stronie serwera, który nam wszystko ładnie posprawdza i wykona odpowiednie operacje z naszymi danymi.


require_once 'recaptchalib.php';

$name = $_POST['name'];
$email = $_POST['email'];
$message = $_POST['message'];
$grecaptcha = $_POST['grecaptcha'];

$secret = '6LekyAoTAAAAALAVXhOdhsjznu7OVHXxzs_42o5E';
$response = NULL;
$reCaptcha = new ReCaptcha($secret);

if(isset($grecaptcha)){
   $response = $reCaptcha->verifyResponse(
      $_SERVER['REMOTE_ADDR'],
      $grecaptcha
   );
}

if($response != NULL && $response->success){
   $to = 'kontakt@dominiknowak.xyz';
   $subject = 'Wiadomość ze strony www';
   $txt = $message;
   $headers = 'From: '. $name . ' ' . $email;

   mail($to,$subject,$txt,$headers);
   print 'success';
}
else{
   print 'error';
}

Ponownie, co się zadziało? Pamiętasz jeszcze o tej bibliotece od Google? Powinieneś mieć skrypt w tym samym katalogu co resztę swoich plików i go dołączyć do skryptu php. Przepisuję wszystkie otrzymane postem obiekty do zmiennych lokalnych (tylko dla własnej wygody). Utworzyłem zmienną o nazwie $secret, w której umieściłem sekretny kod wygenerowany ze strony Google reCAPTCHA. Jest on potrzebny do weryfikacji kodu, który przychodzi od klienta. Na jego podstawie tworzony jest obiekt klasy ReCaptcha z załączonej biblioteki. Wykorzystując metodę tej klasy weryfikujemy klucz utworzony przez klienta po kliknięciu w reCAPTCHA. Jeżeli on będzie prawidłowy i zgodny zn naszymi kluczami to wartość zmiennej success klasy ReCaptcha będzie true. W przykładzie powyżej jeżeli wszystko się zgadza wysyłana jest wiadomość na mój adres mailowy i dodatkowo drukuję na ekran napis success, który jest odczytywany przez skrypt send.js jako poprawnie przeprowadzona operacja. Jednak gdyby klucz się nie zgadzał drukuję error i mogę poprzez skrypt javascript’owy wyświetlić informację o błędzie.

Jak widzisz trudne to nie jest, ale za to bardzo użyteczne. Dzięki takiej metodzie nie musimy przeładowywać strony, żeby zweryfikować użytkownika, a reCAPTCHA ogranicza spam, który wysyłają boty.