Cours "Web d'entreprise en Java"

Sécurité des applications


Objectif du TP :

Réserver l'accès à certaines des pages de l'application à des utilisateurs privilégiés, en utilisant l'authentification par le container.

L'application se repose sur le serveur d'application pour filtrer l'accès aux pages de l'application. Glassfish est supposé pour les corrections. Consultez la documentation de votre serveur pour les parties spécifiques à Glassfish (ces parties sont indiquées clairement). Tous les serveurs d'application ont des concepts semblables pour gérer la sécurité et il ne devrait pas être difficile d'adapter ces corrections à un autre serveur d'application que GlassFish ; en particulier le serveur WebLogic est construit sur un socle commun avec GlassFish.

Support de cours


Protection des pages correspondant à un modèle d'URL

Créez un nouveau projet "tpsecuriteweb" de type Java EE, JSF, avec support de CDI.

Sous le répertoire racine des pages Web de votre application, créez un répertoire nommé "protected" (choisissez un autre nom si vous voulez). Ajoutez dans ce répertoire une page JSF qui affiche "Page protégée" et qui contient un lien vers la page index.xhtml, page d'arrivée ("welcome") du projet (de type <h:outputLink>. Ajoutez un lien vers cette page dans la page index.xhtml.

Testez le projet en passant d'une page à l'autre en utilisant les liens.

Modifiez le fichier web.xml pour que l'accès aux pages placées sous ce répertoire soient protégées par mot de passe. Les pages ne seront accessibles que par les utilisateurs qui ont le rôle de "responsable".

Un rôle peut être attaché à un utilisateur ou à un groupe d'utilisateur. La façon d'attacher un utilisateur ou un groupe dépend du serveur d'application.

Cette partie est indépendante du serveur d'application. Les exercices suivants dépendent du serveur d'application.

Testez à nouveau le projet. Est-ce que la page est protégée ? Comment ?

Correction :

Lignes à ajouter à web.xml

Pages JSF


Remarque importante

N'utilisez pas de caractères accentués ou de caractères spéciaux lorsque vous configurez GlassFish, par exemple dans les descriptions des propriétés que vous ajoutez. NetBeans n'aime pas ça du tout et vous risquez alors de ne pas pouvoir démarrer GlassFish depuis NetBeans.

Si vous n'arrivez plus à démarrer GlassFish, cherchez des caractères spéciaux dans le fichier domain1.xml et enlevez les. Essayez ensuite de démarrer GlassFish à nouveau.


Création d'un utilisateur enregistré ; utilisation du domaine "File" de GlassFish

Dans cet exercice vous allez créer un utilisateur et lui donner un rôle.

Glassfish (comme Tomcat) gère les utilisateurs avec des "realms" (royaumes, domaines dans la traduction en français de Glassfish). Un realm définit le support qui va contenir les informations sur les utilisateurs. Les principaux realms : File (les informations sont enregistrées dans des fichiers), Certificate (les identités sont déterminées par des certificats), LDAP (les informations sont dans un annuaire LDAP) et JDBC (les informations sont enregistrées dans une base de données relationnelle).

Pour commencer vous allez utiliser le domaine le plus simple, File qui conserve les informations sur les utilisateurs dans un fichier du serveur d'application.

Enregistrez l'utilisateur de login "chef" en utilisant le domaine "File". Vous allez utiliser la console d'administration de GlassFish. Pour afficher cette console d'administration, allez dans l'onglet "Services" de NetBeans, entrée "Servers". Clic bouton droit sur GlassFish et choix "View Domain Admin Console". Il faut commencer par démarrer GlassFish si ça n'est pas déjà fait (clic droit sur GlassFish et "Start"). La console d'administration doit s'ouvrir dans une des fenêtres du navigateur Web (le délai d'affichage peut être un peu long). Ouvrez l'entrée "Configurations > server-config > Sécurité > Domaines" et cliquez sur "file". Une page "Modifier le domaine" s'affiche. Cliquez sur "Gérer les utilisateurs". Dans la nouvelle page, cliquez sur le bouton "Nouveau".

Créez l'utilisateur "chef" (mot de passe admin) et mettez-le dans le groupe "admin". Créez l'utilisateur toto (mot de passe toto) et ne le mettez dans aucun groupe.

La manière d'attribuer un rôle d'une application à un groupe d'utilisateurs dépend du serveur d'application. Donnez le rôle de "responsable" (le rôle de l'exercice précédent) à cet utilisateur. Le plus souvent un rôle n'est pas attaché à un utilisateur mais plutôt à un groupe d'utilisateurs. Associez le groupe admin au rôle "responsable" en utilisant le fichier de déploiement de l'application "glassfish-web.xml" lié à GlassFish. Pour créer ce fichier, clic droit dans NetBeans sur l'application, puis "New", type "GlassFish" (passer par "Other" si ce type n'est pas directement visible) et "GlassFish Descriptor" ; vous pouvez taper le code directement ("XML") ou passer par l'interface utilisateur.

Testez l'application. Vous devriez pouvoir faire afficher la page protégée en tapant les login et mot de passe de l'utilisateur "chef". Testez aussi avec l'utilisateur toto (le plus simple est de relancer l'application pour changer d'utilisateur).

Correction :

Fichier glassfish-web.xml


Utilisation d'un domaine JDBC

Le domaine File est trop statique pour beaucoup d'applications, en particulier pour les applications qui permettent aux utilisateurs de créer leur propre compte. Nous allons étudier un autre domaine qui conserve les informations sur les utilisateurs dans des tables relationnelles : le domaine JDBC.

Création des tables dans Java DB

Il faut commencer par créer les tables relationnelles qui vont conserver les informations sur les utilisateurs. Vous aller utiliser Java DB qui est joint à NetBeans.

2 tables :

Dans NetBeans, onglet Services > Databases, clic droit sur l'entrée Java DB et "Create Database" pour créer une nouvelle base de données "securite" avec un utilisateur "toto". Une nouvelle entrée "jdbc:derby://localhost:1527/securite" a dû être créée.

Créez les 2 tables dans le schéma associé à l'utilisateur indiqué lors de la création : clic droit sur le nom du schéma et "Execute Command" et copiez la commande SQL pour créer les 2 tables en les séparant par un ";" :

create table utilisateur (
 nom_utilisateur varchar(10) primary key,
 mot_de_passe varchar(64));
create table groupe (
  nom_groupe varchar(10),
  nom_utilisateur varchar(10) references utilisateur,
  primary key(nom_groupe, nom_utilisateur))

Attention, le nom de la colonne pour le nom d'utilisateur doit être le même que pour les 2 tables ! C'est ce nom qu'il faudra donner au moment de la création du realm dans GlassFish. Le reste des définitions peut être différent ; il peut être intéressant, par exemple, d'ajouter des clés primaires non significatives aux tables. On peut même utiliser des vues SQL à la place des tables, ce qui donne toute liberté pour la définition des tables sous-jacentes.

Cliquer sur l'icône pour faire exécuter les 2 ordres (ou tapez [Ctrl] [Maj] E).

Création d'un pool de connexions

Il faut maintenant créer une source de données dans GlassFish. Pour cela il faut commencer par créer un pool de connexions qui désigne la base de données "securite" qui vient d'être créée.

Console d'administration de GlassFish > Ressources ; clic sur Pools de connexions JDBC ; clic sous Nouveau.
Nom du pool : tpSecuritePool ; type de ressource : javax.sql.DataSource ; clic sur Suivant.
Nom de la classe de la source de données : org.apache.derby.jdbc.ClientDataSource ; clic en bas sur "Ajouter une propriété" et ajouter les propriétés suivantes avec les valeurs que vous avez choisies lors de la création des 2 tables (repecter les majuscules/minuscules) : DatabaseName (securite), User, Password, URL (jdbc:derby://localhost:1527/securite), PortNumber (1527), serverName (localhost).
Clic sur Terminer.

Pour tester, cliquer sur le nouveau pool et cliquer sur "Ping". Il doit s'afficher "Commande Ping réussie" en haut de la page.

Création d'une ressource JDBC

Console d'administration de GlassFish > Ressources ; clic sur Ressources JDBC ; clic sous Nouveau.
Nom JNDI : jdbc/tpSecurite.
Nom du pool : tpSecuritePool.

Création du domain/realm

Pour créer un realm dans Glassfish :

  1. Ouvrir la console d'administration de Glassfish depuis NetBeans (bouton droit et choix "Afficher la console d'adminstration").
  2. Menu Configurations > server-config > Sécurité > Domaines puis cliquer sur "Nouveau".
  3. Saisir les informations sur le nouveau domaine :

    Cliquez sur le bouton Ok pour enregistrer les informations. Il affiche un message d'avertissement ; ne pas en tenir compte.

Entrée des informations dans les tables

Il reste à saisir les informations sur les utilisateurs dans les tables. Pour cela, dans NetBeans, onglet Services > Databases, entrée jdbc:derby://localhost:1527/securite ; TOTO, clic droit sur la table UTILISATEUR, choix View Data..., icône la plus à gauche (Insert Record(s)) ou Alt I.

Utiliser un site Web pour obtenir le hash de vos mots de passe ; par exemple http://hash.online-convert.com/sha256-generator ou http://www.xorbin.com/tools/sha256-hash-calculator. La valeur que vous devez entrer dans la base dépend du codage indiqué dans la définition du domaine (normalement Hex). Sachez, par exemple, que "toto" donne "31f7a65e315586ac198bd798b6629ce4903d0899476d5741a9f32e2e521b6a66" en hex et "MfemXjFVhqwZi9eYtmKc5JA9CJlHbVdBqfMuLlIbamY=" en base64.

Ajoutez 2 nouveaux utilisateurs chef2 (dans le groupe admin) et toto2 (dans aucun groupe).

Utilisation du domaine/realm

Il reste à configurer l'application pour que le nouveau domaine soit utilisé plutôt que le domaine "file".

Ajoutez ces lignes dans web.xml :

 <login-config>
   <auth-method>BASIC</auth-method>
   <realm-name>domaine_securite</realm-name>
 </login-config>

Test

Refaites les mêmes tests que dans l'exercice précédent avec des utilisateurs chef2 (groupe admin) et toto2.

En cas de problème

Examinez aussi l'onglet "Glassfish Server 3" en bas de la fenêtre de NetBeans.

Aller voir les fichiers de log de Glassfish : "Entreprise Server" dans la colonne de gauche de la console d'administration de Glassfish, puis cliquer le bouton "Afficher les journaux".

Au besoin, augmenter le niveau des logs : aller dans le fichier <repertoire installation de Glassfish>\glassfish\domains\domain1\config\logging.properties (sous Windows le répertoire domains peut se trouver à un autre endroit qu'on peut faire afficher par un clic droit sur le serveur dans l'onglet Services, et en choisissant Properties ; il s'agit du "Domains Folder") et passer le niveau pour la sécurité à FINEST au lieu de INFO : javax.enterprise.system.core.security.level=FINEST (au lieu de INFO)

Pas besoin de relancer Glassfish pour qu'il prenne en compte cette modification.

Ca permettra peut-être d'afficher les requêtes SQL lancées pour la vérification des utilisateurs ou d'avoir des informations qui vous aideront à résoudre le problème.

Lorsque le problème est réglé, repasser ensuite le niveau à INFO pour éviter trop de messages de log.

Il est aussi possible de passer Glassfish en mode deboggage : <jvm-options>-Djava.security.debug=logincontext</jvm-options>

asadmin create-jvm-options -Djava.security.debug=logincontext  
Vous pouvez aussi aller voir le fichier XML de configuration de Glassfish placé en <répertoire installation de Glassfish>\glassfish\domains\domain1\config\domain.xml

Formulaire personnalisé

Le mode Basic pose souvent des problèmes car le navigateur garde des informations sur l'utilisateur qui vient de se connecter, même si on programme un logout de la session. Un formulaire personnalisé ne pose pas ce type de problème.

Écrivez un formulaire personnalisé pour la saisie du login et du mot de passe de l'utilisateur.

Correction

web.xml
login.xhtml
noaut.xhtml


Page d'erreur et déconnexion

Pour éviter les complications dans le cas où l'utilisateur n'a pas tapé le bon login, écrivez une page d'erreur qui affiche un message d'erreur et permet de sortir de la session dans le cas où une erreur HTTP 403 (pas d'autorisation) a eu lieu.

Correction

web.xml
pasautorise.xhtml
Visiteur.java


Retour