Blue Flower

Dans cet article, nous allons aborder les points suivants :

  • comment gérer l'authentification et la gestions des droits dans une application web et plus particulièrement dans le cas de Glassfish
  • la notion de session HTTP

 

 

 

Authentification avec un file realm

Un realm est un domaine de sécurité. Un serveur Glassfish en possède plusieurs :

  • un admin-realm. ce domaine sert à indiquer quels sont les utilisateurs ayant accès à la console d'administration de Glassfish
  • un file realm, pour permettre la gestion des utilisateurs : stocke le login et le mot de passe
  • un certificat realm pour gérer l'authentification via des certificats.

Un file realm est donc un domaine de sécurité où les utilisateurs et les groupes de sécurités sont définis dans un fichier. Ce fichier est géré par Glassfish, on déclare donc dans celui-ci :

  • des groupes d'utilisateurs
  • des utilisateurs définis par un login et un mot de passe. On définit à quel(s) groupe(s) appartiennent ces utilisateurs.

Pour l'exemple, définissez dans le file realm de Glassfish les utilisateurs suivants :

  • les groupes appuser et appadmin
  • les utilisateurs bob et alice; bob fait partie de appuser, alice fait partie des deux groupes.

file realm

 Attention, ce fichier n'est pas propre à votre application, il peut servir à toutes les applications du domaine glassfish.

C'est pourquoi, dans le fichier web.xml, vous allez définir pour chaque ressource quel est le rôle ayant les droits nécessaires. Le rôle indiqué n'est pas le rôle défini dans le file realm. Par exemple, ci-dessous, les URL en admin sont réservées au groupe admin, les autres URL sont réservées aux utilisateurs authentifiés :

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee          http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.jsf</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>index.jsf</welcome-file>
    </welcome-file-list>
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Admin Pages</web-resource-name>
            <url-pattern>/admin/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>admin</role-name>
        </auth-constraint>
    </security-constraint>
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>AllPages</web-resource-name>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>user</role-name>
        </auth-constraint>
    </security-constraint>
    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>file</realm-name>
    </login-config>
</web-app>

 

Il faut par conséquent un fichier de plus permettant de faire la correspondance entre les groupes du file realm et les rôles que vous avez définis pour votre application. Ce fichier est le fichier glassfish-web.xml. Ci-dessous un exemple de ce fichier glassfish-web.xml :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app error-url="">
    <context-root>/filerealmauth</context-root>
    <security-role-mapping>
        <role-name>admin</role-name>
        <group-name>appadmin</group-name>
    </security-role-mapping>
    <security-role-mapping>
        <role-name>user</role-name>
        <group-name>appuser</group-name>
    </security-role-mapping>
    <class-loader delegate="true"/>
</glassfish-web-app>

 

Cas de l'autorisation via file realm basic

Nous testons ici l'authentification de type BASIC. (cf fichier web.xml, section login-config)  Le navigateur proposera automatiquement une pop-up permettant la saisie du login/mot de passe.  

Pour tester l'exemple, créer les pages web suivantes, le contenu importe peu

  • la page d'accueil index.xhml
  • une page page1.xhtml
  • une page admin/admin1.xhtml

Pour comprendre comment se passe l'authentification, lancer Wireshark, puis lancer votre navigateur sur la page d’accueil. Vous verrez alors successivement :

  • que votre navigateur réalise un GET /filerealmauth/ => c'est l'url de la page d'accueil

authentification phase 1

  • glassfish répond HTTP 401 Unauthorized => la pop-up apparaît permettant de saisir le login/mot de passe, ce que vous faites avec alice comme login

authentification phase 2

  • votre navigateur réalise un GET /filerealmauth/ mais cette fois-ci en fournissant en clair le login/mot de passe!!

authentification phase 3

  • glassfish renvoie à présent la page demandée en fournissant un identifiant de session

authentification phase 3

Conclusion : c'est une méthode très peu sécurisée, les mots de passe circulent en clair. 

 

Cas de l'autorisation via file realm form

La seule différence avec la méthode d'authentification précédente et le renvoie par Glassfish vers une page de login spécifique (à développer donc) au lieu de la pop-up du navigateur.

Pour ce faire, il faut donc :

  • modifier le fichier web.xml afin de préciser ce nouveau mode d'authentification
  • coder la page de login.

 

Le fichier web.xml

...
<login-config> <auth-method>FORM</auth-method> <realm-name>file</realm-name> <form-login-config> <form-login-page>/login.jsf</form-login-page> <form-error-page>/loginerror.jsf</form-error-page> </form-login-config> </login-config>
...

La page de login 

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html">
    <h:head>
        <title>Login</title>
    </h:head>
    <h:body>
        <p>Veuillez saisir votre login et mot de passe
        </p>
        <form method="POST" action="j_security_check">
            <table cellpadding="0" cellspacing="0" border="0">
                <tr>
                    <td align="right">Username:&nbsp;</td>
                    <td><input type="text" name="j_username"/></td>
                </tr>
                <tr>
                    <td align="right">Password:&nbsp;</td>
                    <td><input type="password" name="j_password"/></td>
                </tr>
                <tr>
                    <td></td>
                    <td><input type="submit" value="Login"/></td>
                </tr>
            </table>
        </form>
    </h:body>
</html>

Analyse des échanges réseau

Pour comprendre comment se passe l'authentification, lancer Wireshark, puis lancer votre navigateur sur la page d’accueil. Vous verrez alors successivement :

  • le navigateur reçoit la page de login, celle-ci contenant un identifiant de session

  • l'utilisateur saisit son login/mot de passe, le mot de passe est à nouveau envoyé en clair