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
.
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 :
className
: la classe d'implémentation de l'interface
org.apache.catalina.Server
. En principe on n'en change pas, et l'on peut omettre cet attribut, qui prendra alors sa valeur par défaut.
port
: le port d'arrêt (
shutdown
) de Tomcat. Ce port ne correspond pas au port HTTP écouté par Tomcat, mais à un port sur lequel Tomcat reçoit la commande de s'arrêter. Lorsque l'on tape la commande
shutdown
sur l'invite de commande, cet ordre est émis, et Tomcat s'éteint alors.
shutdown
: la commande envoyée sur ce port.
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
Exemple 2. Exemple d'élément
Server
<Server port="9005" shutdown="SHUTDOWN"> <!-- contenu de l'élément --> </Server>
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 :
className
: nom de la classe Java qui implémente l'interface
org.apache.catalina.Service
. Peut être omis, dans ce cas l'implémentation par défaut est choisie.
name
: nom logique de ce service, doit être unique au sein de tous les services définis dans un serveur.
Exemple 3. Exemple d'élément
Service
<Service name="Catalina"> <!-- contenu de cet élément --> </Service>
port
: le port que ce connecteur écoute.
enableLookups
: autorise ou non les requêtes DNS lorsqu'une servlet invoque la méthode
request.getRemoteHost()
. Une requête DNS est un processus éventuellement coûteux. Si
enableLookups
est à
false
, alors
request.getRemoteHost()
retourne l'adresse IP plutôt que le nom de domaine associé.
maxPostSize
: la taille maximale des requêtes
POST
supportée par ce serveur. La valeur par défaut est fixée à 2Mo. Une valeur de -1 signifie qu'il n'y a pas de limite.
maxThreads
: indique le nombre maximal de requêtes que ce connecteur peut traiter à la fois (une requête est traitée dans son propre thread par le connecteur HTTP). Au-delà de cette limite, les requêtes sont placées dans une file d'attente.
acceptCount
: taille maximale de la file d'attente des requêtes. Si des requêtes supplémentaires arrivent, alors elles sont rejetées.
protocol
: cet attribut peut prendre deux types de valeur, un nom de protocole, tel que
HTTP/1.1
, ou un nom de classe. Les trois classes supportées par défaut sont :
org.apache.coyote.http11.Http11Protocol
: correspond au protocole HTTP/1.1 standard.
org.apache.coyote.http11.Http11NioProtocol
: correspond au protocole HTTP construit sur l'API NIO.
org.apache.coyote.http11.Http11AprProtocol
: correspond au protocole construit sur l'APR (Apache Portable Runtime, qui est la librairie runtime utilisée par Apache 2.2).
mod_proxy
: permet de communiquer avec Apache 2.2.*.
Exemple 4. Exemple d'éléments
Connector
<!-- Port standard d'écoute de requêtes HTTP sur le port 8080 --> <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" maxThread="100" maxCount="100" redirectPort="8443" /> <!-- Port standard d'écoute de requête Apache AJP/1.3 sur le port 8009 --> <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
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 :
name
: le nom de ce moteur, notamment utilisé dans les fichiers journal ;
defaultHost
: l'hôte virtuel par défaut vers lequel diriger cette requête.
Exemple 5. Exemple d'élément
Engine
<Engine name="Catalina" defaultHost="localhost"> <!-- contenu de l'élément Engine --> </Engine>
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 :
name
: le nom de cet hôte virtuel ;
appBase
: l'
application base
pour cet hôte. Il s'agit du répertoire contenant les applications web pour cet hôte. Il peut s'agir d'un chemin absolu, ou d'un chemin relation au répertoire
$CATALINA_BASE
. La valeur par défaut de cet attribut est
true
.
autoDeploy
: indique à Tomcat s'il doit charger automatiquement les applications web qui sont copiées dans le répertoire
appBase
. Le cas échéant, Tomcat scrute le contenu de ce répertoire à intervalles de temps réguliers, afin de détecter de nouveaux répertoires, ou de nouveaux fichiers
.war
.
deployOnStartup
: indique à Tomcat s'il doit charger les applications web se trouvant dans
appBase
lors de son démarrage. La valeur par défaut de cet attribut est
true
.
workDir
: répertoire de travail propre à cet hôte. Par défaut, Catalina utilise un sous-répertoire de
$CATALINA_BASE/work
pour chaque hôte, mais il est possible d'en choisir un autre. On peut accéder à ce répertoire d'une servlet, via l'attribut d'application
javax.servlet.context.tempdir
.
unpackWARs
: indique à Catalina qu'il doit exécuter les applications web de cet hôte dans un répertoire de travail avant de les exécuter. La valeur par défaut de cet attribut est
true
.
deployXML
: indique à Catalina s'il peut ou non prendre en compte les fichiers
/META-INF/context.xml
des applications web. La valeur par défaut de cet attribut est
true
.
Exemple 6. Exemple d'élément
Host
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <!-- contenu de l'élément Host --> </Host>
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 :
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 :
Context
doit être associé à un unique attribut
path
, qui représente le chemin vers cette application web.
Context
doit être associé à un chemin vide. C'est cette application qui servira toutes les requêtes non servies par les autres applications.
Exemple 7. Exemple de variable d'environnement
<Environment name="maxRetry" type="java.lang.Integer" value="10" override="false"/>
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.
Exemple 8. Exemple de
Resources
:
UserDatabase
<Resource name="UserDatabase" auth="Container" type="org.apache.catalina.UserDatabase" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" pathname="conf/tomcat-users.xml" />
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.
Exemple 9. Exemple de
Resources
: serveur de mail
<Resource name="mail/Session" auth="Container" type="javax.mail.Session" mail.smtp.host="localhost"/>
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 :
Exemple 10. Configuration d'un
Realm
JDBC
<Realm className="org.apache.catalina.realm.JDBCRealm" driverName="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql:/db_user" connectionName="admin_db" connectionPassword="passwd" userTable="t_user" userNameCol="user_name" userCredCol="passwd" userRoleTable="t_role" roleNameCol="role_name" />
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.
Exemple 11. Configuration d'un
Realm
sur une
DataSource
<Realm className="org.apache.catalina.realm.DataSourceRealm" dataSourceName="jdbc/UserDataSource" userTable="t_user" userNameCol="user_name" userCredCol="passwd" userRoleTable="t_role" roleNameCol="role_name" />
Realm
JDBC.
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
:
Exemple 12. Valve de journalisation
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="fichier_log" resolveHosts="false" rotatable="true" fileDateFormat="yyyy-MM-dd.HH"/>
fichier_log
, dans le répertoire
$CATALINA_BASE/logs
. Ce fichier subira une rotation toutes les heures, ce qui est fixé par la valeur de l'attribut
yyyy-MM-dd.HH
. L'attribut
resolveHost
décide si une requête DNS est faite afin d'enregistrer le nom d'hôte du client, ou juste son adresse IP.
Exemple 13. Valve de filtrage par adresse IP
<Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="192.168.1.*" deny="192.168.0.*"/> <Valve className="org.apache.catalina.valves.RemoteHostValve" allow="*.fr" deny="*.com"/>
allow
est présent, alors la requête
doit
correspondre à sa valeur. S'il n'est pas présent, alors la requête est acceptée,
sauf
si elle correspond à la valeur de l'attribut
deny
. Dans tous les cas, une requête qui correspond à la valeur de l'attribut
deny
est rejetée.
Notons enfin que l'attribut
deny
de
RemoteHostValve
est décodé en utilisant la expressions régulières Java (package
java.util.regex
).
RequestDumperValve
permet d'enregistrer dans un fichier l'intégralité des paramètres d'une requête HTTP. Elle ne doit être utilisée qu'en phase de mise au point d'une application, sous peine de saturer rapidement le disque dur.
SingleSignOn
: permet de s'authentifier sur plusieurs applications web d'un même hôte virtuel ;
BasicAuthenticator
et
DigestAuthenticator
: permettent de forcer l'authentification HTTP
basic
ou
digest
pour l'accès à une application web.
FormAuthenticator
et
SSLAuthenticator
: activent l'authentification par formulaire, en mode normal ou SSL.