IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

[ Java ] Mise en place d'un singleton dans mon cas ?


Sujet :

Langage Java

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    88
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 88
    Par défaut [ Java ] Mise en place d'un singleton dans mon cas ?
    Bonjour,

    Je suis actuellement en train de repenser la partie 'sécurité' d'une application web.

    Je souhaiterais avoir d'un côté un fichier plat qui serait fourni dans mon War.
    Ce fichier plat contiendrait la liste des actions Struts et les droits associés à ces actions.

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    /admin/listerUtilisateur.do=Admin
    /gestion/listerFacture.do=Admin,Comptable
    Ce fichier porte un nom fixé à l'avance 'lesDroits.acl'.

    Ensuite, je voudrais écrire une classe qui irait charger le contenu de ce fichier. Appelons la SecurityManager.

    Cette classe là, je n'aurais besoin de l'instancier qu'une seule fois puisque les droits de l'application ne vont pas changer quand l'appli tourne

    C'est là que je me dis qu'un Singleton pourrait convenir pour mon SecurityManager.

    Problème, je ne sais pas comment charger mon fichier 'lesDroits.acl' puisque :
    - selon le contexte de l'application (répertoire de déploiement), le chemin change.
    - d'après la doc que j'ai lue, impossible de passer un paramètre à un singleton (contexte de l'appli via un objet HttpRequest par ex)

    J'espère avoir été clair ...

    Merci de vos lumières

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 277
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 277
    Par défaut
    Pourquoi ne pas sécuriser ton appli de façon standard à partir du web.xml ?
    Je suppose que tu dois avoir tes raisons...

    Pour ton fichier, s'il fait partie de ton application web, même archive war ou répertoire, je ne sais pas comment tu déploies, tu dois pouvoir y accéder sans problème, quel que soit le répertoire de déploiement.

    S'il ne fait pas partie de ton application, effectivement, c'est plus ennuyeux.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    88
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 88
    Par défaut
    Je vais essayer de répondre le plus précisèment possible.

    La société utilise déjà un framework propriétaire.
    Ce framework charge les roles des utilisateurs via un annuaire LDAP.
    Il les compare avec les autorisations décrites dans un fichier plat.

    Mais notre application utilise d'autres informations qui sortent du cadre du framework.
    Pour simplifier, chaque utilisateur a en plus des rôles, des propriétés métier qui lui sont associées.

    Le framework ne gère pas ces propriétés bien entendu.
    Il faut donc les gérer à part.

    Pour l'instant, ce 'à part' signifie que l'on a un boût de code dans chaque Action Struts nécessitant un contrôle.
    La sécurité est donc diluée un peu partout dans le code.

    Je voudrais donc recentraliser cette 'sécurité spécifique' via un seul fichier de config et la mise en place d'un SecurityManager.


    Pour ce qui est du chargement de mon fichier de config, il fait bien partie de l'appli.
    Je pense qu'il faut spécifier chemin = contexte + 'lesDroits.acl'.

    Donc soit 'je pense' MAL (pas besoin du contexte pour charger le fichier) soit je ne sais pas/vois pas comment récupérer le contexte

    Merci

  4. #4
    Membre chevronné
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    442
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 442
    Par défaut
    Qui t'as dit que l'on ne pouvait pas passer de paramètre à un singleton ?!

    Il y a juste un souci en java avec le double-checked locking (c'est lié au compilateur qui en fait un peu trop), mais le code suivant fonctionne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    public class Singleton
    {
    	private static Singleton INSTANCE = null;
    	private static Map<String, String> _properties = null;
     
    	private String _user;
     
    	private Singleton(String user)
    	{
    		_user = user;
    	}
     
    	public static void init(Map<String, String> properties)
    	{
    		_properties = properties;
    	}
     
    	public static Singleton getInstance()
    	{
    		if (INSTANCE == null)
    		{
    			synchronized(Singleton.class)
    			{
    				loadSingleton();
    			}
    		}
    		return INSTANCE;
    	}
     
    	private static synchronized void loadSingleton()
    	{
    		if (INSTANCE == null)
    		{
    			INSTANCE = new Singleton(_properties.get("username"));
    		}
    	}
    }
    Bien sûr il faut être sûr d'appeler Singleton.init() avant la première demande Singleton.getInstance(), sinon renvoyer une exception...

  5. #5
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 277
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 277
    Par défaut
    Tu peux lire ton fichier à partir d'un ServletContext et de la méthode getResourceAsStream par exemple.
    Le ServletContext s'obtient de plusieurs manières il me semble: HttpSession, HttpServlet...
    A voir.

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    88
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 88
    Par défaut
    Citation Envoyé par Duc Lebowski Voir le message
    Qui t'as dit que l'on ne pouvait pas passer de paramètre à un singleton ?!
    C'est ce que j'avais cru comprendre en lisant ceci
    Citation Envoyé par Duc Lebowski Voir le message
    Il y a juste un souci en java avec le double-checked locking (c'est lié au compilateur qui en fait un peu trop), mais le code suivant fonctionne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    public class Singleton
    {
    	private static Singleton INSTANCE = null;
    	private static Map<String, String> _properties = null;
     
    	private String _user;
     
    	private Singleton(String user)
    	{
    		_user = user;
    	}
     
    	public static void init(Map<String, String> properties)
    	{
    		_properties = properties;
    	}
     
    	public static Singleton getInstance()
    	{
    		if (INSTANCE == null)
    		{
    			synchronized(Singleton.class)
    			{
    				loadSingleton();
    			}
    		}
    		return INSTANCE;
    	}
     
    	private static synchronized void loadSingleton()
    	{
    		if (INSTANCE == null)
    		{
    			INSTANCE = new Singleton(_properties.get("username"));
    		}
    	}
    }
    Bien sûr il faut être sûr d'appeler Singleton.init() avant la première demande Singleton.getInstance(), sinon renvoyer une exception...
    Ok je vois un peu l'idée.
    Par contre j'avais lu sur dvp que le double-checked locking n'était pas une méthode sûre d'instancier un singleton ...

    Source

    Je vais essayer de trouver une implémentation satisfaisante.

    Merci

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    88
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 88
    Par défaut
    Citation Envoyé par fr1man Voir le message
    Tu peux lire ton fichier à partir d'un ServletContext et de la méthode getResourceAsStream par exemple.
    Le ServletContext s'obtient de plusieurs manières il me semble: HttpSession, HttpServlet...
    A voir.
    Oui, je pensais faire un truc du genre.
    Ton post me conforte dans cette idée !
    Reste plus qu'à insérer tout ça dans mon singleton :d

    Merci

  8. #8
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 277
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 277
    Par défaut
    Pour en revenir au singleton, la manière la plus simple et plus correcte est quelque chose commme ça:

    public class Singleton
    {
    private static Singleton singleton = new Singleton();

    private Singleton() {}

    public static Singleton getInstance()
    {
    return singleton;
    }
    }

    A vérifier (j'espère ne pas avoir fait d'erreurs), mais il me semble que c'est ce qui est recommandé, notamment par l'auteur du bouquin Java Efficace.

  9. #9
    Membre chevronné
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    442
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 442
    Par défaut
    Le vrai double-checked s'écrit comme celà :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public static Singleton getInstance()
    {
    	if (INSTANCE == null) {
    		synchronized(Singleton.class) {
    			if (INSTANCE == null) {
    				synchronized(Singleton.class) {
    					INSTANCE = new Singleton(_properties.get("username"));
    				}
    			}
    		}
    	}
    	return INSTANCE;
    }

    Le problème que j'avais vu à l'époque (ce n'est peut-être plus vrai), est que le compilateur Java considère qu'il peut optimiser le code et transfome en celà, ce qui est faux :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public static Singleton getInstance()
    {
    	if (INSTANCE == null) {
    		synchronized(Singleton.class) {
    			INSTANCE = new Singleton(_properties.get("username"));
    		}
    	}
    	return INSTANCE;
    }
    Par contre en passant par une méthode à part pour instancier le singleton, normalement c'est bon, quoique apparemment il y a encore des problèmes : cf http://www.ibm.com/developerworks/ja...ary/j-dcl.html

  10. #10
    Membre chevronné
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    442
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 442
    Par défaut
    J'avais pas réfléchi, au pire tu peux l'instancier dans la méthode init(Map<String, String> properties) si tu es sûr qu'elle sera appelée en premier et par une seule personne (ce qui est ton cas puisque ce sera dans une Servlet dédiée exécutée uniquement 1 fois au démarrage du serveur).

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    88
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 88
    Par défaut MERCI !!!!
    Ca fonctionne

    Déjà, il faut écrire dans le web.xml l'emplacement du fichier à lire.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        <context-param>
    		<param-name>Rights</param-name>
    		<param-value>/WEB-INF/config/rights.properties</param-value>
    	</context-param>
    Puis écrire la classe du singleton a peu prêt comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
     
    public class SecurityManager {
     
        /**
         * Création de l'instance au niveau de la variable.
         */
        private static final SecurityManager INSTANCE = new SecurityManager();
     
        private static Map accessMap = new Hashtable();
     
        /**
         * Initialise le singleton
         * Charge la liste des droits dans un HashTable
         * 
         * @param theRequest
         * @throws FwkSystemException
         */
        public static void init(HttpServletRequest theRequest)
            throws FwkSystemException
        {        
            // Lit le path du fichier de config dans web.xml
            String filePath = theRequest.getSession().
                getServletContext().getInitParameter("Rights");
     
            // Charge le fichier
            InputStream stream = theRequest.getSession().
                getServletContext().getResourceAsStream(filePath);                       
     
            try
            {
                /**
                 * Conversion du InputStream en BufferedReader
                 * Permet une gestion du fichier à la ligne
                 */            
                BufferedReader bufferedReader = 
                    new BufferedReader( new InputStreamReader(stream) );           
     
    	      String line;                // Ligne courante du fichier de config
     
                // Tant qu'il reste des lignes
                while ( (line=bufferedReader.readLine()) != null ){                         
    			[...]
    		}         
            }catch(FileNotFoundException exc){
                [...]
            }catch(IOException exc){
                [...]
            }        
     
        }
     
        /**
         * La présence d'un constructeur privé supprime
         * le constructeur public par défaut.
         */
        private SecurityManager() {
     
        }
     
        /**
         * Dans ce cas présent, le mot-clé synchronized n'est pas utile.
         * L'unique instanciation du singleton se fait avant
         * l'appel de la méthode getInstance(). 
         * Aucun risque d'accès concurrents.
         * Retourne l'instance du singleton.
         */
        public static SecurityManager getInstance(){
            return INSTANCE;
        }
     
        /**
         * @return accessMap
         */
        public static Map getAccessMap() {
            return accessMap;
        }
     
        public ActionErrors isGranted([...]){
            [...]
        }
     
    }
    Merci pour votre aide

  12. #12
    Membre chevronné
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    442
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 442
    Par défaut
    Juste un petit truc de conception, évite de promener l'objet technique HttpServletRequest dans tes objets. Dans ton cas tu peux utiliser une Map de paramètres par exemple à la place.

    L'interface Map va te permettre de briser la dépendance entre le contexte web et ton SecurityManager (plus évolutif).

  13. #13
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    88
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 88
    Par défaut
    Super, merci pour la précision

    Je suis largement demandeur de ce genre d'astuces !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Mise en place de sous-domaines dans mon application.
    Par slake13 dans le forum Glassfish et Payara
    Réponses: 0
    Dernier message: 12/05/2009, 17h27
  2. Mise en place d'un scm dans mon pom
    Par MLK jr dans le forum Maven
    Réponses: 2
    Dernier message: 16/06/2008, 12h42
  3. [AJAX] Mise en place d'un réponse dans Ajax.Request via JSON
    Par polothentik dans le forum Général JavaScript
    Réponses: 0
    Dernier message: 13/05/2008, 10h05
  4. [VBA-E]Mise en place de 2 valeurs dans une meme cellule
    Par baptbapt dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 25/08/2006, 16h06
  5. Réponses: 2
    Dernier message: 05/04/2006, 12h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo