Java & le web
x Le web dynamique
x Java & le web

Intro à Tomcat
x Serveur d'applications
x Présentation Tomcat
x Installation
x Arborescence

Configuration
x Introduction
x Server
x Service
x Engine
x Host
x Context
x DefaultContext
x Logger
x Loader
x Realm
x Valve

Connecteurs
x Balise Connector
x Coyote HTTP/1.1

Sécurisation accès
x La balise Realm
x Memory Based
x JDBC Database
x Protéger ressources
x Cryptage password

Les Valve
x La balise Valve
x Access Log
x Single Sign-On

Fonctionnalités
x Déploiement auto.
x Class loaders

Eclipse & Tomcat
x Plug-in pour Eclipse
x Projet Tomcat
x Debugger des JSP

Créer une appli web
x Présentation
x Architecture
x Fichier web.xml
x Déploiement

Tomcat 5
x Nouveautés

Tomcat's Corner
x Crédits
x Liens
 
             
Sécuriser l'accès aux ressources

 

 

Introduction

Dans Tomcat, grâce aux Realms, il est possible de protéger l'accès aux ressources du serveur, en demandant aux utilisateurs de s'authentifier. Le principe est simple (tout le monde l'a déjà rencontré sur un site) : lorsque l'utilisateur tente d'accéder à l'URL d'une ressource protégée, une boîte de dialogue lui demande son login (nom d'utilisateur) et son mot de passe.

Nous expliquons ailleurs comment configurer différents Realm dans Tomcat. Nous allons à présent voir comment sécuriser une ressource, à travers le différents types d'authentification pouvant être mis en place.

 

 

Contraintes de sécurité

Protéger l'accès à une ressource consiste à lui appliquer une contrainte de sécurité. Cette contrainte sera définie au sein d'une application, donc dans le descripteur de déploiement web.xml situé dans le répertoire WEB-INF de l'application web. Toute l'application ne sera pas nécessairement sécurisée, nous allons pouvoir définir quelles ressources sont à protéger.

Au sein de ce fichier (donc, entre les balises <web-app> et </web-app>), on définit une contrainte de sécurité entre les balises <security-constraint> et </security-constraint>. Nous allons étudier les paramètres classiques de sécurité à travers un exemple :

 

<web-app>
...

<security-constraint>
<display-name>Sécurité sous Tomcat</display-name>

<web-resource-collection>
<web-resource-name>Ressource protégée</web-resource-name>
<url-pattern>/appli/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>

<auth-constraint>
<role-name>admin</role-name>
<role-name>user</role-name>
</auth-constraint>

</security-constraint>
...
</web-app>

Comme dans les différentes configurations de déploiement, on fournit un nom pour notre contrainte de sécurité (display-name). On entre ensuite dans le vif du sujet.

L'élément web-resource-collection décrit les ressources pour lesquelles la contrainte va s'appliquer. La balise web-resource-name donne un nom à cet ensemble de ressources. Nom qui pourra être réutilisé dans certaines demandes d'authentification.

L'élément url-pattern permet de définir pour quelles URL la contrainte doit être mise en oeuvre. C'est donc ici que l'on sélectionne les ressources à protéger. Comme d'habitude, il s'agit d'une pattern, on peut donc notamment utiliser le caractère '*'. Dans notre exemple, toutes les URL commençant par "/appli/" seront concernées par la contrainte. Comme d'habitude, il s'agit d'une URL relative à celle du Context de l'application, puisque nous sommes dans le descripteur de déploiement de cette webapp.

Grâce aux balises http-method, on peut définir les méthodes HTTP concernées par la contrainte. On pourra ainsi indiquer que l'accès à telle ressource par la méthode GET doit être protégée, mais pas l'accès à cette même ressource par la méthode POST. Dans notre exemple, on protège les deux.

Une fois définies les ressources à protéger, il convient de préciser quels utilisateurs, et plus exactement quels rôles peuvent y avoir accès. Entre les balises auth-constraint, on peut donc indiquer les role-name ayant le droit d'accéder aux ressources définies plus haut. Ces noms de rôles doivent bien sûr correspondre aux rôles que Tomcat connaît, à travers le Realm utilisé dans cette application.

Une fois la ou les contrainte(s) de sécurité définie(s), nous allons spécifier le mode de login (authentification) des utilisateurs. Plusieurs possibilités s'offrent à nous : authentification basique (boîte de dialogue), ou par formulaire (donc personnalisable).

 

Authentification basique

Toujours dans le descripteur de déploiement, on va pouvoir, après les security-constraint configurer le processus de login des utilisateurs. Cela se fait dans un élément XML nommé login-config. Le contenu de cet élément varie selon la méthode d'authentification. Nous allons tout d'abord nous intéresser à la méthode basique. Elle consiste en une boîte de dialogue, gérée par le client web (votre navigateur), qui demande le login (nom d'utilisateur) et le mot de passe. Elle envoie ensuite l'information au serveur qui se charge des vérifications nécessaires. Attention, si l'on peut mettre plusieurs contraintes de sécurités dans une webapp, un seul login-config est acceptable, ce qui est logique...

Voici, à travers un exemple, comment fonctionne la configuration de l'authentification basique :

<web-app>
...

<security-constraint>
...
</security-constraint>

<login-config>
<auth-method>BASIC</auth-method>
<realm-name>Authentification pour Tomcat</realm-name>
</login-config>

...
</web-app>

Cela aura pour effet, lorsque l'utilisateur demandera une URL protégée, d'afficher la boîte de dialogue suivante dans le navigateur :

C'est côté client qu'est géré cet aspect. C'est le navigateur qui propose cette boîte de dialogue. Elle diffère donc d'un navigateur à l'autre (ici, FireFox). Le login et le mot de passe saisis sont transmis au serveur. De son côté, il se charge de vérifier que le nom d'utilisateur est connu, et le mot de passe correct. Puis il vérifie que cet utilisateur a bien l'un des rôles nécessaires pour accéder à la ressource, donc qu'il répond à la contrainte de sécurité.

Cette méthode d'authentification (HTTP BASIC) n'est évidemment pas sécurisée dans la mesure où les informations circulent en clair sur le réseau (y compris le mot de passe), et que rien n'assure de la fiabilité du serveur de destination (pas de certificat...). Bref, une authentification à éviter pour une application de banque en ligne, mais suffisante (et largement répandue) pour des applications dans lesquelles la sécurité n'est pas draconienne (petit forum...).

 

Authentification par Digest

Nous passerons très vite sur cette méthode, qui n'est pas l'une des plus importantes (elle n'est pas dans les spécifications de Servlet). Nous avons vu que, dans un Realm, on peut définir un attribut digest, indiquant la méthode de Digest à utiliser pour stocker les mots de passe. Plusieurs méthodes sont utilisables, notamment le célèbre MD5.

La configuration dans Tomcat est extrêmement semblable à celle de l'authentification basique. La balise auth-method doit simplement contenir la valeur DIGEST au lieu de BASIC.

Là encore, la boîte de dialogue gérée par le client web s'ouvre, demandant les mêmes informations. La différence réside dans le fait que le mot de passe est crypté (MD5...) avant d'être envoyé au serveur. Bien sûr, il doit également être stocké crypté dans le Realm utilisé. C'est à cette seule condition que la comparaison effectuée par Tomcat entre le mot de passe fourni et le mot de passe attendu aboutira.

Cette méthode est donc plus sécurisée que la basique. Cela dit, le transport n'est toujours pas sécurisé. Et cette méthode n'est pas supportée par tous les navigateurs.

 

Authentification par formulaire

L'authentification par formulaire est très intéressante, en ce qu'elle permet au développeur de l'application d'avoir la main sur l'aspect graphique de l'authentification. Cela permet ainsi d'insérer les champs login et mot de passe dans une page du site, respectant la charte graphique, et pouvant contenir d'autres éléments (textes, images...). Beaucoup moins spartiate que la boîte de dialogue côté navigateur...

Voici comme l'on configure cette authentification :

<web-app>
...

<security-constraint>
...
</security-constraint>

<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/error.jsp</form-error-page>
</form-login-config>
</login-config>

...
</web-app>

Notons tout d'abord que l'auth-method est FORM. Ensuite, des éléments spécifiques apparaissent, au sein de la balise form-login-config. On précise la page web (HTML, JSP) contenant les champs pour s'authentifier (form-login-page). Et la page à retourner en cas d'erreur (form-error-page), qui peut donc elle aussi être personnalisée...

La page de login (form-login-page) doit contenir des éléments bien précis. Son formulaire doit contenir, dans son attribut action, la valeur "j_security_check". Le champ du formulaire permettant de saisir le login doit s'intituler "j_username", et celui du mot de passe "j_password". Ces dénominations sont absolument obligatoires. Mettons cela tout de suite en pratique avec un exemple tout simple :

<form method="POST" action="j_security_check">
<table>
<tr>
<td>Login :</td>
<td><input type="text" name="j_username"></td>
</tr>
<tr>
<td>Mot de passe :</td>
<td><input type="password" name="j_password"></td>
</tr>
<tr>
<td><input type="submit" value="Entrer !"></td>
<td><input type="reset" value="Annuler"></td>
</tr>
</table>
</form>

Avec cette méthode par formulaire, lorsqu'un utilisateur demande l'accès à une ressource protégée, le serveur enregistre une sauvegarde de la requête HTTP en cours (celle qui demande la ressource protégée) et redirige l'utilisateur (nouvelle requête HTTP donc) vers la page de login. L'utilisateur peut alors saisir ses login et mot de passe. Ceux-ci sont vérifiés par le Realm. Si l'authentification a fonctionné (login et mot de passe corrects), et que l'utilisateur répond à la contrainte de sécurité (a un rôle autorisé), le serveur rebascule sur la requête HTTP initiale. Sinon, il envoie la page d'erreur configurée.

 

Authentification SSL

Dans le cadre de la mise en place d'un serveur Tomcat sécurisé, il faut activer SSL dans les contraintes de sécurité (security-constraint). Il convient alors d'ajouter une user-data-constraint, comme présenté ci-dessous :

<web-app>
...

<security-constraint>
...
<user-data-constraint>
    <transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>

...
</web-app>

La transport-guarantee à CONFIDENTIAL active le SSL dans l'authentification (si les échanges avec le serveur sont sécurisés, bien sûr).

 

Single Sign-On

La Valve Single Sign-On peut être intéressante lorsque l'on met en place des mécanismes d'authentification dans Tomcat.