niedziela, 7 marca 2010

Użycie recaptcha w javie

Recaptcha
Zaczynamy od stworzenia sobie konta na recaptcha i dodajemy domenę na której nasz kod będzie używany. Jeśli nie zamierzamy udostępniać naszej aplikacji w internecie, to możemy wymyślić sobie tymczasową domeną, np. global-key.pl. Musimy tylko pamiętać aby zaznaczyć checkbox (Enable this key on all domains (global key)) dzięki któremu będziemy mogli korzystać z naczego klucza także na serwerach produkcyjnych czy testowych (takich jak localhost czy 127.0.0.1). Następnie klikamy Create Key.
Wszystko powinno wyglądać mniej więcej tak:


Do implementacji recaptcha będziemy potrzebowali biblioteki recaptcha4j-0.0.7.jar. Plik jar należy umieścić w katalogi WebContent\WEB-INF\lib lub w innym katalogu gdzie przechowujemy biblioteki dla naszej aplikacji. 

Przygotowanie formularza
Kiedy mamy już wygenerowany prywatny i publiczny klucz, czas wstawić do formularza pola które będą przechowywać wartości recaptcha. Do tego celu użyjemy tego skryptu napisanego w JavaScript:
<script type="text/javascript"
   src="http://api.recaptcha.net/challenge?k=<your_public_key>">
</script>


<noscript>
   <iframe src="http://api.recaptcha.net/noscript?k=<your_public_key>"
       height="300" width="500" frameborder="0"></iframe><br>
   <textarea name="recaptcha_challenge_field" rows="3" cols="40">
   </textarea>
   <input type="hidden" name="recaptcha_response_field" 
       value="manual_challenge">
</noscript>

W powyższym skrypcie wstawiamy nasz Public Key w miejsce <your_public_key> i tak przygotowany fragment kodu wklejamy do naszego formularza. U mnie wygląda to tak:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!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">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Login</title>
</head>
<body>
 <form action="success" method="post">


  <div>
   Value1: <input type="text" name="value1"/>
  </div>
  
  <div>
   Value2: <input type="text" name="value2"/>
  </div>
  
  <div>
   <script type="text/javascript"
      src="http://api.recaptcha.net/challenge?k=<publicKey>">
   </script>
   <noscript>
       <iframe src="http://api.recaptcha.net/noscript?k=<publicKey>"
           height="300" width="500" frameborder="0"></iframe><br />
       <textarea name="recaptcha_challenge_field" rows="3" cols="40">
       </textarea>
       <input type="hidden" name="recaptcha_response_field" 
           value="manual_challenge" />
   </noscript>
  </div>
  
  <div>
   <input type="submit" value="Wyslij" />
  </div>
 
 </form>
</body>
</html>





Możemy teraz uruchomić naszą aplikację i sprawdzić czy recaptcha działa, na tym etapie powinna się tylko wyświetlić na stronie.
Nadszedł czas na stworzenie logiki biznesowej która odbierze formularz z recaptchą. Ja do tego celu użyję serwletu. 


package com.blogspot.mkorwel.servlet;


import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


import net.tanesha.recaptcha.ReCaptchaImpl;
import net.tanesha.recaptcha.ReCaptchaResponse;
/**
 * 
 * @author mkorwel
 *
 */
public class Success extends HttpServlet {
  private static final long serialVersionUID = 1L;


  protected void doGet(HttpServletRequest request,
    HttpServletResponse response) throws ServletException, IOException {


  }


  protected void doPost(HttpServletRequest request,
    HttpServletResponse response) throws ServletException, IOException {


   //Pobranie i wypisanie naszych danych z formularza
   System.out.println(request.getParameter("value1"));
   System.out.println(request.getParameter("value2"));
   
   //Pobranie danych dla recaptcha
   String challengeReCaptcha = request.getParameter("recaptcha_challenge_field");
   String responseReCaptcha = request.getParameter("recaptcha_response_field");
   String remoteAddr = request.getRemoteAddr(); //Address użytkonika
      
   //Wypisanie danych dla recaptcha
   System.out.println(challengeReCaptcha);
   System.out.println(responseReCaptcha);
   System.out.println(remoteAddr);
   
   ReCaptchaImpl reCaptcha = new ReCaptchaImpl();
   //ustawiamy nasz klucz prywatny
      reCaptcha.setPrivateKey("<privateKey>");
      
      //sprawdzamy czy użytkownik wpisał pobrany wyraz w recaptcha
      ReCaptchaResponse reCaptchaResponse =
          reCaptcha.checkAnswer(remoteAddr, challengeReCaptcha, responseReCaptcha);
      
      if (!reCaptchaResponse.isValid()) {
       response.sendRedirect("/index.jsp");
      } else {
       getServletConfig().getServletContext().getRequestDispatcher(
    "/result.jsp").forward(request, response);
      }
   
  }
}

Krótkie wyjaśnienie co dzieje się w servlecie.
W metodzie doPost na początku pobieramy nasze dane z formularza aby wypisać je na ekran. Następnie pobieramy dane dla recaptcha, tj. dwa pola które umieściliśmy na stronie: recaptcha_challenge_field i recaptcha_response_field oraz adres użytkownika który wpisywał recaptcha. Po wczytaniu potrzebnych danych tworzymy obiekt ReCaptchaImpl i ustawiamy nasz klucz prywatny. W tym momencie mamy już wszystkie dany które potrzebne nam są do zweryfikowania poprawnoście recaptcha, dlatego tworzymy obiekt ReCaptchaResponse na którym wywołujemy metode checkAnswer z klasy ReCaptchaImpl którą kilka linijek temu stworzyliśmy. Do sprawdzenia czy użytkownik wpisał pobrany wyraz dla recaptcha używamy metody isValid. W Serwlecie w razie błędnego wpisania kodu, użytkownik zostaje przekierowany do strony z formularzem, a jeśli kod jest poprawny, idzie do strony która wyświetla ekran powitalny.

Brak komentarzy:

Prześlij komentarz