Configuration de Tomcat

La configuration de Tomcat passe par l'édition du fichier server.xml qui se trouve dans le répertoire conf de l'installation. Ce fichier XML se découpe en différents éléments, qui correspondent à des notions propres à Tomcat, que nous allons voir une par une.

Ces éléments XML se divisent en deux groupes. Le premier est constiué des éléments conteneur : Engine : Host et Context. Ces éléments s'imbriquent les uns dans les autres suivant des règles très précises, et sont obligatoires. Le second groupe est constitué d'éléments facultatifs et flottants, au sens où ils peuvent être placés dans les différents conteneurs : GlobalNamingResources, Resources, Realm et Valve.

L'unique élément racine Server modèlise un serveur Catalina dans sa totalité. Catalina est le nom du serveur proprement dit, alors que Tomcat est le nom du projet complet. Tout ce qui est défini dans cet élément est global au serveur, et sera donc appliqué, entre autres, à toutes les applications web qu'il supporte. Techniquement, un server est un élément XML, et une interface Java : org.apache.catalina.Server.

Cet élément supporte trois attributs :

Seul l'attribut port est réellement susceptible d'être modifié. Cette modification est même nécessaire si l'on installe plusieurs Tomcat en même temps sur une même machine.

L'élément server accepte trois type d'enfants : des Listener, un GlobalNamingResources et des Service

Un service est un container dans lequel on peut trouver autant de sous-éléments Connector que l'on veut, et un unique sous-élément Engine. On peut définir autant de services que l'on veut au sein d'un serveur donné, à condition qu'ils diffèrent tous par leurs noms.

Cet élément possède deux attributs :

Un connecteur est un objet Java capable d'écouter un port précis et comprenant un protocole précis. À chaque protocole supporté par Tomcat est associé une classe Java de connecteur. Chaque connecteur dirige ensuite les requêtes qu'il reçoit au moteur de servlets défini dans ce service. Donc un moteur de servlet donné peut répondre à des requêtes en provenance de plusieurs ports, et suivant des protocoles différents.

Quel que soit le connecteur choisi, un certain nombre d'attributs sont toujours disponibles :

L'élément Engine modélise le moteur de servlet proprement dit. À chaque serveur Catalina est associé un unique moteur de servlet, auquel on accède via des connecteurs. Un moteur peut comporter plusieurs sous-éléments Host, chacune représentant un hôte virtuel.

Toutes les implémentations par défaut de cet élément supportent les attributs suivants :

Cet élément modélise un hôte virtuel. Un hôte virtuel doit être associé à l'adresse IP de ce serveur, via un DNS ou un fichier hosts. Si l'attribut defaultHost du moteur dans lequel se trouve cet hôte est défini, alors au moins un des hôtes doit obligatoirement posséder ce nom.

Toutes les implémentations de Host doivent supporter les attributs suivants :

L'implémentation par défaut supporte en plus les attributs suivants.

Enfin, l'élément Context modélise une application web. Cet élément est un peu particulier, car il peut se trouver en plusieurs endroits.

Historiquement (Tomcat v4), cet élément se trouvait nécessairement dans le fichier server.xml de Tomcat. Cette façon de faire posait deux problèmes :

Ce problème a été levé, et il est maintenant possible de placer cet élément dans un fichier context.xml rangé dans le répertoire META-INF de l'application.

La prise en compte ou non de ce fichier à cet endroit peut être réglé par l'administrateur de Tomcat (attribut deployXML de l'élément Host). S'il choisit de ne pas prendre en compte ces fichiers, alors Tomcat ira chercher ce fichier ailleurs, dans un endroit contrôlé par l'administrateur.

On peut définir autant d'éléments Context que l'on veut dans un hôte virtuel, avec une restriction :

Cet élément permet de configurer des ressources et des variables d'environnement, qui seront ensuite disponibles pour toutes les applications web gérées par cette instance de Tomcat. La distribution par défaut nous donne l'exemple de la base d'utilisateurs reconnue par cet instance de Tomcat.

Voyons tout d'abord un exemple de définition d'une variable d'environnement.

Notons que l'attribut name, qui représente le nom de la variable créée, est relatif au context java:comp/env. Dans notre exemple, le nom JNDI complet de la variable sera donc java:comp/env/maxRetry.

Examinons maintenant la ressource définie dans le server.xml par défaut.

Toute ressource doit posséder un nom (attribut name) et un type, sous forme d'une classe Java. Cette ressource UserDatabase sera donc représentée par un objet de type UserDatabase, que Tomcat peut construire grâce à la classe factory MemoryUserDatabaseFactory.

Cet objet a besoin du paramètre suivant pour s'initialiser : pathname, qui lui indique dans quel fichier les utilisateurs sont définis.

On peut définir des ressources très diverses, les plus fréquentes sont les connexions aux bases de données, disponibles sous forme de DataSource, ou aux serveurs de mail.

Nous verrons dans la suite comment il est possible d'accéder à ces ressources d'une application web.

Un Realm est une notion qui appartient à l'environnement de sécurité de Java, défini par JAAS (Java Authentification and Authroization Service) pour la partie JSE et JCCA pour la partie JEE. Par définition, un Realm est un ensemble d'utilisateurs qui partagent la même méthode d'authentification. Techniquement pour Tomcat, un Realm est défini par cette méthode d'authentification.

Comme il a été dit, un élément Realm est un élément qui peut être inclus dans plusieurs éléments conteneur du fichier conf/server.xml de Tomcat : Engine, Host ou Context. Un élément Realm inclus dans un élément parent est automatiquement hérité dans les éléments enfants. Ainsi, un Realm défini dans un Host (donc au niveau d'un hôte virtuel) sera automatiquement pris en compte par tous les Context (donc les applications web) de ce Host.

Un élément Realm permet d'associer des droits d'utilisation aux application web. Un tel élément modélise une base d'utilisateurs et rôles, qu'il est ensuite possible d'utiliser pour restreindre l'utilisation de certaines applications.

Tomcat propose plusieurs implémentations de Realm. Nous en avons déjà vu une : org.apache.catalina.realm.MemoryRealm, qui utilise le fichier tomcat-users.xml. Les autres implémentations permettent notamment de lire la liste des utilisateurs et des rôles dans des bases de données, qui elles-mêmes peuvent être administrées par ailleurs.

Le choix d'une implémentation particulière se fait en fixant une valeur à l'attribut className de l'élément Realm.

Examinons une de ces implémentations : org.apache.catalina.realm.JDBCRealm. Dans cette implémentation, les utilisateurs sont enregistrés dans une table. Tomcat a besoin de plusieurs informations pour y accéder :

Voici un exemple d'un tel élément.

On reconnaît sans problème les paramètres de connexion à la base parmi les attributs de cet élément. Viennent ensuite les paramètres de la table contenant les utilisateurs. Tomcat utilise deux colonnes : userNameCol porte les noms des utilisateurs, et userCredCol leurs mots de passe. Notons que par défaut les mots de passe sont stockés en clair, mais qu'il est possible de configurer ce Realm pour qu'ils soient cryptés. Enfin, viennent les paramètres de la table des rôles : userRoleTable porte le nom de cette table et userRoleTable le nom de la colonne qui contient les noms des rôles. Cette table doit aussi comporter une colonne userNameCol, qui réalise la jointure entre la table des utilisateurs et celle des rôles.

Il existe également une implémentation de Realm capable de s'adresser à une DataSource directement : org.apache.catalina.realm.DataSourceRealm. La DataSource est obtenue par une requête JNDI dont le nom est donné en paramètre. Voyons un exemple.

Les attributs permettant de lire les tables d'utilisateurs et de rôles sont les mêmes que pour le Realm JDBC.

De même que l'élément Realm, l'élément Valve peut se placer dans les conteneurs Engine, Host et Context. De même que pour le Realm, une valve définie au niveau d'un conteneur s'applique à ses sous-conteneurs. Une valve est un élément utilitaire, qui peut avoir différentes fonctions, qui s'insère dans le processus de traitement d'une requête, et realise un certain traitement. À chaque type de valve est associé un traitement particulier.

Un élément Valve comporte toujours un attribut className, qui indique quelle implémentation de Valve est utilisée pour cet élément. Suivent ensuite une liste d'attributs propres à chaque implémentation.

Voyons les principales implémentations de Valve :