Recherche sur le blog

samedi 23 octobre 2010

[Web] Zend : les éléments de base

Chose promise, chose due ! En effet, votre apprentissage Zend n’est pas terminé. Le dernier article traitait, si votre mémoire est encore fraîche, de la structure basique d’un projet d’application. En effet lorsque vous créez celui-ci vous retrouvez différents dossiers mais aussi divers fichiers ayant tous une fonction spécifique. Nous allons voir brièvement leurs tâches.

La classe “bootstrap”

Cette classe permet de configurer l’application avant son lancement (un peu comme le fichier “index.php” qui contient la configuration de l’environnement). Le bootstrap contient au moins ces deux fonctions :

  • initAutoLoad() qui permet de charger n’importe quel composant Zend dans toute l’application sans avoir à utiliser une seule directive “include” ou “require”.
  • initViewHelpers() qui permet d’initialiser par exemple le layout commun au vue ou bien de définir un titre global pour les pages.

Le fichier de configuration “application.ini”

Il permet de définir des ressources et d’autres éléments de configuration comme les informations de connexion à une base de données (nom d’utilisateur, serveur, mot de passe, nom du schéma). Cela ressemble un peu à un fichier properties en Java, car il contient des paires “clé-valeur”.

Les contrôleurs (Zend Controller)

Le contrôleur, un peu à l’image d’une servlet, permet de traiter les requêtes qui lui sont envoyées. Par défaut, on retrouve deux contrôleurs (sous forme de classes) :

  • IndexController, qui contient une action “index” prédéfinie. L’exemple à la fin de ce paragraphe permet simplement de définir le titre de la page “index” qui sera affiché lors de l’appel du contrôleur et de l’action “index”.
  • ErrorController, qui traite les erreurs (comme les erreurs 404, par exemple, qui survient lorsque la page n’existe pas).

public function indexAction()
{
     $this->view->title = "Hello World !";
 

Les vues

Ce sont les dossiers associés aux contrôleurs. Ainsi chaque contrôleur a une vue (l’IndexController possède une vue “index”). Chaque vue possède une ou plusieurs pages, qui sont en fait associées aux actions dans les contrôleurs.

Les modèles

Dans un schéma MVC, il est important d’utiliser les modèles pour les accès aux données ou pour d’autres opérations logiques. Par exemple on peut faire hériter un modèle de la classe Zend_Db_Table, qui sera finalement une représentation d’une table de notre schéma. Zend Framework intègre en fait son propre ORM (Object Relational Mapper) et son propre pilote MySQL. Voici un modèle de base pour une table “User” qui contient, entre autre, un champ “idUser” :

class Model_User extends Zend_Db_Table
{
    protected $_name = "User";  // Table name in DB
 
    public function getUser($idUserVar)
    {
       $row = $this->fetchRow('idUser = ' . $idUserVar);
       return $row;
    }
}

Les formulaires

Il est possible de créer des formulaires grâce aux classes fournies par Zend. Cela peut faciliter la chose si on n’y connait rien en HTML. Cependant les formulaires Zend présentent des inconvénients majeurs :

  • Difficulté de personnalisation.
  • Impossibilité de voir le code que cela va générer. Il faut analyser le code source lors de l’exploration de la page.
  • Validation des champs un à un.

Mais encore ?

Bien sûr, il existe d’autres éléments mais revenir immédiatement sur la description de ceux-ci risquerait de vous perturber dans votre découverte.

mardi 5 octobre 2010

[Web] Utilisation d'un reCAPTCHA en JSP-servlets

Amis développeurs, vous qui appréciez sans doute la programmation Java et plus particulièrement la programmation web en utilisant à la fois JSP et servlets, nous allons voir ensemble comment créer un reCAPTCHA (plus précisément : insertion du widget de saisie du challenge anti-robot dans la page JSP et vérification de la réponse de l'utilisateur dans la servlet). Ce petit tutorial est basé sur la documentation  se trouvant sur le site de Google reCAPTCHA. En visitant ce site, il vous est possible de vous enregistrer afin d'obtenir une paire de clés publique et privée pour un domaine internet en particulier. Ainsi si vous êtes en local (par exemple sur un serveur Apache Tomcat), vous pouvez simplement utiliser l'adresse "http://localhost". Inutile d'indiquer le numéro de port de l’instance de votre serveur.

Une fois l'inscription effectuée, vous recevrez la paire de clés. Notez-les bien car celles-ci seront utilisées pour utiliser le service de reCAPTCHA. N’oubliez pas qu’elles ne sont valables que pour le domaine donné.
 
La classe contenant les clés

Créons au préalable une classe "Constantes" qui comprendra les deux clés (sous forme de chaînes de caractères). Par exemple :
 
package utils;  
 
public class Constantes
{
    // Recaptcha Keys      
    static final public String REC_PUBLICKEY = "6Lcxd...AE";
    static final public String REC_PRIVATEKEY = "6Lcxd...AM";
}
 
Librairie reCAPTCHA

Vous devez maintenant télécharger la librairie reCAPTCHA sous forme d'un .jar à inclure dans votre projet web. Vous trouverez la librairie en cliquant sur ce lien. Pour ma part j'ai utilisé la version "recaptcha4j-0.0.7", c’est-à-dire la dernière en date du 23 octobre 2010.

Le code de la JSP

Le tout est maintenant de créer un formulaire d'enregistrement qui comprendra un champ "login", un champ "mot de passe" et le reCAPTCHA en question. Voici le code d'exemple suivi de quelques explications détaillées.
 
<@page import="utils.Constantes" %>;
<@page import="net.tanesha.recaptcha.ReCaptcha" %>;
<@page import="net.tanesha.recaptcha.RecaptchaFactory" %>;
 
<html>
  <body>
    <form action="Login" method="post">
       <input name="action" type="hidden" value="register" />
       <input name="login" type="text" value="" size="30" />
       <input name="password" value="" size="30" />
       <%
          ReCaptcha c =
ReCapthaFactory.newReCaptcha(Constantes.REC_PUBLICKEY, Constantes.REC_PRIVATEKEY, false);
          out.print(c.createRecaptchaHtml(null,null));
       %>
       <input type="submit" value="S’enregistrer" />
    </form>
  </body>
</html>

Tout d'abord il faut importer la classe contenant les constantes précédemment créées (donc les clés privée et publique). Ensuite, afin d'afficher le widget reCAPTCHA nous avons besoin d'importer les classes nécessaires à son bon fonctionnement : on importe donc les classes "ReCaptcha" et "ReCaptchaFactory". Enfin dans une balise de code, nous créons une nouvelle instance du widget grâce à la méthode statique "newReCaptcha()" de la factory. Il ne reste plus qu'à créer et à afficher le widget là où on le désire.

Le code côté serveur

Dans la servlet "Login", nous récupérons le paramètre caché du formulaire, à savoir "action". On effectue le traitement du formulaire uniquement celui-ci vaut "register". Voici un exemple de code à utiliser (N.B. : la définition de la classe et les méthodes d'initialisation n'ont pas été indiquées dans ce cas) :
 
package servlets;
 
import utils.Constantes;
import net.tanesha.recaptcha.ReCaptchaImpl;
import net.tanesha.recaptcha.ReCaptchaResponse;
 
(...)
 
  protected void processRequest(...)
  {
    String action = request.getParameter("action");
    if(action.equals("register"))
    {
      register(request,response);
    }
  }
 
  public void register(...)
  {
     // Récupérer les champs et analyse reCAPTCHA
     ReCaptchaImpl reC = new ReCaptchaImpl();
     reC.setPrivateKey(Constantes.REC_PRIVATEKEY);
    
     String remoteAddr = request.getRemoteAddr();
     String challenge = request.getParameter("recaptcha_challenge_field");
     String response = request.getParameter("recaptcha_response_field");
    
     ReCaptchaResponse reCR = reC.checkAnswer(remoteAddr, challenge, response);
 
     if(!reCR.isValid()) {
           // Traitement si le reCAPTCHA est invalide.
     }
  }

En aucun cas vous ne devez oublier les deux importations de classes en début de la servlet qui utilisera le reCAPTCHA. Dans le code ci-dessus, lorsque l'implémentation du reCAPTCHA a été créée et que la clé privée a été définie, il faut récupérer les paramètres tels que le challenge mais aussi l'adresse distante et la réponse au challenge. Donc dans le code ci-dessus,
  • remoteAddr : adresse IP de l'utilisateur (envoyée aux serveurs reCAPTCHA).
  • response : contient la réponse de l'utilisateur pour le challenge donné.
  • challenge : est le challenge qui a été donné à l'utilisateur.
La méthode "checkAnswer()" compare alors la réponse au challenge pour l'utilisateur dont l'adresse distante est renseignée. Si la réponse est invalide on peut par exemple lancer une exception.

Une option doit être rajoutée à la JVM de Tomcat pour rafraichir régulièrement le cache DNS. Sous NetBeans, il est possible d'ajouter l'option suivante via les options du projet :

-Dsun.net.inetaddr.ttl=30

Si votre instance de Tomcat ne fonctionne pas via NetBeans et qu'elle est installée comme service, vous pouvez utiliser la méthode indiquée dans la documentation officielle. N'hésitez pas à lire cet article pour en savoir plus à ce sujet. Vous devriez maintenant être apte à créer vos formulaires sécurisés. Bon amusement !