Blog jak widać już nie jest aktualizowany. I raczej nie będzie. Wisi sobie ot tak, ze względów historycznych :)

reCaptcha i Ruby on Rails

Krzysztof Rygielski | 2009-11-16 17:59 | Kategorie: Rails

Jakiś czas temu zainteresowałem się mechanizmem captcha i tym, jak zintegrować go ze stroną napisaną w Ruby on Rails. Natknąłem się na reCaptcha.

Projekt reCaptcha służy przede wszystkim sluży przepisywaniu książek do postaci cyfrowej. Mechanizmy OCR nie radzą sobie z niektórymi starymi tekstami. Zatem poszczególne słowa muszą być przepisywane przez ludzi. Użytkownikom udostępniono narzędzie, którego mogą używać w swoich serwisach jako trudne do odczytania przez boty captcha. Jednocześnie wpisując odczytane z obrazka słowa użytkownicy wypełniający formularz przyczyniają się do przepisywania książek do komputerów. Dwie pożyteczne rzeczy za jednym zamachem :-)

Istnieje plugin do rails, który pozwala stosować reCaptcha w serwisach tworzonych w tym frameworku. Można zainstalować to jako globalny gem lub jako plugin do pojedyńczej aplikacji. Ja wybrałem pierwsze rozwiązanie. Aktualnie projekt został przeniesiony z githuba na gemcutter. Aby móc używać gemcuttera, instalujemy go:

# gem install gemcutter

Następnie wywołujemy komendę:

# gem tumble

i od tej pory gemcutter został dodany do źródeł i jest ustawiony jako główne repozytorium gemów. Teraz instalujemy plugin:

# gem install recaptcha

Zanim zaczniemy używać reCaptcha, należy zarejestrować się w serwisie i wygenerować klucze publiczny i prywatny. Cała procedura jest opisana po zarejestrowaniu więc pozwolę sobie ją pominąć.

Klucz prywatny i publiczny umieszczamy w pliku config/environment.rb naszej aplikacji:

ENV['RECAPTCHA_PUBLIC_KEY'] = 'klucz_publiczny'
ENV['RECAPTCHA_PRIVATE_KEY'] = 'klucz_prywatny'

Oczywiście aby gem był używany podczas działania dopisujemy też w environment.rb następującą linijkę:

require 'recaptcha/rails'

Teraz możemy zacząć zabawę :-) W formularzu, w którym chcemy używać reCaptcha wystarczy dopisać w wybranym miejscu wywołanie metody recaptcha_tags. Umieszczona bez żadnych argumentów załaduje standardowe reCaptcha, jakie można zobaczyć np. tutaj. Oczywiście standardowy wygląd może nie pasować do całości układu graficznego naszej strony. Można wprowadzać drobne modyfikacje np:

recaptcha_tags :display=>{:theme=>'white'}

spowoduje wyświetlenie motywu w kolorze białym. Można też podawać tam różne inne opcje opisane w api reCaptcha. Najlepiej kombinować metodą prób i błędów :-)

W przypadku kiedy nasz formularz jest wysyłany przy użyciu AJAXa, wówczas reCaptcha nie będzie zachowywać się prawidłowo. Należy wówczas dodatkowo dopisać argument :ajax=>true

recaptcha_tags :ajax=>true

Mała uwaga: W przypadku instalacji z github, najnowszą możliwą wersją będzie 0.2.2. W tej wersji występuje błąd, który powoduje, że używając opcji :ajax nie da się korzystać z innych opcji, np. :display. Po prostu nie przyniosą one żadnego efektu. Po zwróceniu się do developera pojawiła się poprawka. Ja zwyczajnie wprowadziłem tą zmianę do pliku /usr/lib/ruby/gems/1.8/gems/ambethia-recaptcha-0.2.2/lib/recaptcha/client_helper.rb. Po jej wprowadzeniu plugin działa już poprawnie.W repozytoriach gemcutter znajduje się najnowsza wersja pluginu przemianowana z ambethia-recaptcha na po prostu recaptcha

Skoro mamy już dodane do formularza pole z kodem reCaptcha, należy sprawdzać czy przepisany kod jest poprawny. W tym celu używamy metody verify_recaptcha. W metodzie obsługującej formularz która u mnie wygląda mniej więcej tak:

def create
  @comment = Comment.new(params[:comment])
  if @comment.save
    flash[:message] = "Dzięki za komentarz"
    @comment = Comment.new
  end
end

dopisuję do instrukcji warunkowej wywołanie w następujący sposób:

if verify_recaptcha(:model=>@comment, :message=>"Przepisz poprawny kod reCaptcha") and @comment.save

W ten sposób sprawdzana jest poprawność kodu i, jeśli nie jest on prawidłowy, do listy błędów wypisywanych za pomocą error_messages_for zostanie dodane powiadomienie.

Jeszcze jedna rzecz. Jesli chcemy, możemy całkowicie zmienić wygląd reCaptcha. Wystarczy wywołać recaptcha_tags w następujący sposób:

recaptcha_tags :display=>{:theme=>'custom'}

Wówczas nie jest generowany żaden kod html, trzeba go napisać samemu stosując się do wytycznych podanych również tutaj. Najważniejsze aby na stronie znajdował się div (chociaż ja zastosowałem element span) o id równym recaptcha_image oraz pole tekstowe do wpisania kodu o id oraz name równym recaptcha_response_field